mirror of
https://github.com/argoproj/argo-cd
synced 2026-04-21 17:07:16 +00:00
Simplify server certificate and known hosts management (#1807)
This commit is contained in:
parent
641e344c7f
commit
9cf744f435
60 changed files with 6122 additions and 520 deletions
|
|
@ -107,7 +107,6 @@ RUN groupadd -g 999 argocd && \
|
|||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY hack/ssh_known_hosts /etc/ssh/ssh_known_hosts
|
||||
COPY hack/git-ask-pass.sh /usr/local/bin/git-ask-pass.sh
|
||||
COPY --from=builder /usr/local/bin/ks /usr/local/bin/ks
|
||||
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
|
||||
|
|
@ -116,6 +115,13 @@ COPY --from=builder /usr/local/bin/kustomize1 /usr/local/bin/kustomize1
|
|||
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
|
||||
COPY --from=builder /usr/local/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
|
||||
|
||||
# support for mounting configuration from a configmap
|
||||
RUN mkdir -p /app/config/ssh && \
|
||||
touch /app/config/ssh/ssh_known_hosts && \
|
||||
ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
|
||||
|
||||
RUN mkdir -p /app/config/tls
|
||||
|
||||
# workaround ksonnet issue https://github.com/ksonnet/ksonnet/issues/298
|
||||
ENV USER=argocd
|
||||
|
||||
|
|
|
|||
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
|
@ -1652,9 +1652,11 @@
|
|||
"gopkg.in/src-d/go-git.v4/config",
|
||||
"gopkg.in/src-d/go-git.v4/plumbing",
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport",
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport/client",
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport/http",
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport/ssh",
|
||||
"gopkg.in/src-d/go-git.v4/storage/memory",
|
||||
"gopkg.in/src-d/go-git.v4/utils/ioutil",
|
||||
"gopkg.in/yaml.v2",
|
||||
"k8s.io/api/apps/v1",
|
||||
"k8s.io/api/batch/v1",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
# p, <user/group>, <resource>, <action>, <object>
|
||||
|
||||
p, role:readonly, applications, get, */*, allow
|
||||
p, role:readonly, certificates, get, *, allow
|
||||
p, role:readonly, clusters, get, *, allow
|
||||
p, role:readonly, repositories, get, *, allow
|
||||
p, role:readonly, projects, get, *, allow
|
||||
|
|
@ -16,6 +17,9 @@ p, role:admin, applications, update, */*, allow
|
|||
p, role:admin, applications, delete, */*, allow
|
||||
p, role:admin, applications, sync, */*, allow
|
||||
p, role:admin, applications, override, */*, allow
|
||||
p, role:admin, certificates, create, *, allow
|
||||
p, role:admin, certificates, update, *, allow
|
||||
p, role:admin, certificates, delete, *, allow
|
||||
p, role:admin, clusters, create, *, allow
|
||||
p, role:admin, clusters, update, *, allow
|
||||
p, role:admin, clusters, delete, *, allow
|
||||
|
|
|
|||
|
|
|
@ -49,7 +49,7 @@
|
|||
"ApplicationService"
|
||||
],
|
||||
"summary": "List returns list of applications",
|
||||
"operationId": "ListMixin5",
|
||||
"operationId": "ListMixin1",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
"ApplicationService"
|
||||
],
|
||||
"summary": "Create creates an application",
|
||||
"operationId": "CreateMixin5",
|
||||
"operationId": "CreateMixin1",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
"ApplicationService"
|
||||
],
|
||||
"summary": "Update updates an application",
|
||||
"operationId": "UpdateMixin5",
|
||||
"operationId": "UpdateMixin1",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
"ApplicationService"
|
||||
],
|
||||
"summary": "Get returns an application by name",
|
||||
"operationId": "GetMixin5",
|
||||
"operationId": "Get",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -238,7 +238,7 @@
|
|||
"ApplicationService"
|
||||
],
|
||||
"summary": "Delete deletes an application",
|
||||
"operationId": "DeleteMixin5",
|
||||
"operationId": "DeleteMixin1",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -769,13 +769,89 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/certificates": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"CertificateService"
|
||||
],
|
||||
"summary": "List all available certificates",
|
||||
"operationId": "ListMixin2",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A file-glob pattern (not regular expression) the host name has to match.",
|
||||
"name": "hostNamePattern",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The type of the certificate to match (ssh or https).",
|
||||
"name": "certType",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The sub type of the certificate to match (protocol dependent, usually only used for ssh certs).",
|
||||
"name": "certSubType",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1alpha1RepositoryCertificateList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"CertificateService"
|
||||
],
|
||||
"summary": "Creates the requested certificates on the server",
|
||||
"operationId": "CreateMixin2",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1alpha1RepositoryCertificateList"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1alpha1RepositoryCertificateList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"CertificateService"
|
||||
],
|
||||
"operationId": "DeleteMixin2",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1alpha1RepositoryCertificateList"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/clusters": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"ClusterService"
|
||||
],
|
||||
"summary": "List returns list of clusters",
|
||||
"operationId": "List",
|
||||
"operationId": "ListMixin3",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -797,7 +873,7 @@
|
|||
"ClusterService"
|
||||
],
|
||||
"summary": "Create creates a cluster",
|
||||
"operationId": "Create",
|
||||
"operationId": "CreateMixin3",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -824,7 +900,7 @@
|
|||
"ClusterService"
|
||||
],
|
||||
"summary": "Update updates a cluster",
|
||||
"operationId": "Update",
|
||||
"operationId": "UpdateMixin3",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -857,7 +933,7 @@
|
|||
"ClusterService"
|
||||
],
|
||||
"summary": "Get returns a cluster by server address",
|
||||
"operationId": "GetMixin1",
|
||||
"operationId": "GetMixin3",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -880,7 +956,7 @@
|
|||
"ClusterService"
|
||||
],
|
||||
"summary": "Delete deletes a cluster",
|
||||
"operationId": "Delete",
|
||||
"operationId": "DeleteMixin3",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -930,7 +1006,7 @@
|
|||
"ProjectService"
|
||||
],
|
||||
"summary": "List returns list of projects",
|
||||
"operationId": "ListMixin3",
|
||||
"operationId": "ListMixin4",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -952,7 +1028,7 @@
|
|||
"ProjectService"
|
||||
],
|
||||
"summary": "Create a new project.",
|
||||
"operationId": "CreateMixin3",
|
||||
"operationId": "CreateMixin4",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -979,7 +1055,7 @@
|
|||
"ProjectService"
|
||||
],
|
||||
"summary": "Get returns a project by name",
|
||||
"operationId": "GetMixin3",
|
||||
"operationId": "GetMixin4",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1002,7 +1078,7 @@
|
|||
"ProjectService"
|
||||
],
|
||||
"summary": "Delete deletes a project",
|
||||
"operationId": "DeleteMixin3",
|
||||
"operationId": "DeleteMixin4",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1052,7 +1128,7 @@
|
|||
"ProjectService"
|
||||
],
|
||||
"summary": "Update updates a project",
|
||||
"operationId": "UpdateMixin3",
|
||||
"operationId": "UpdateMixin4",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1162,7 +1238,7 @@
|
|||
"RepositoryService"
|
||||
],
|
||||
"summary": "List returns list of repos",
|
||||
"operationId": "ListMixin2",
|
||||
"operationId": "List",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1184,7 +1260,7 @@
|
|||
"RepositoryService"
|
||||
],
|
||||
"summary": "Create creates a repo",
|
||||
"operationId": "CreateMixin2",
|
||||
"operationId": "Create",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -1211,7 +1287,7 @@
|
|||
"RepositoryService"
|
||||
],
|
||||
"summary": "Update updates a repo",
|
||||
"operationId": "UpdateMixin2",
|
||||
"operationId": "Update",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1244,7 +1320,7 @@
|
|||
"RepositoryService"
|
||||
],
|
||||
"summary": "Delete deletes a repo",
|
||||
"operationId": "DeleteMixin2",
|
||||
"operationId": "Delete",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
|
|
@ -1342,13 +1418,46 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/repositories/{repo}/validate": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"RepositoryService"
|
||||
],
|
||||
"summary": "ValidateAccess validates access to a repository with given parameters",
|
||||
"operationId": "ValidateAccess",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/repositoryRepoResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/session": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"SessionService"
|
||||
],
|
||||
"summary": "Create a new JWT for authentication and set a cookie if using HTTP.",
|
||||
"operationId": "CreateMixin7",
|
||||
"operationId": "CreateMixin8",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -1373,7 +1482,7 @@
|
|||
"SessionService"
|
||||
],
|
||||
"summary": "Delete an existing JWT cookie if using HTTP.",
|
||||
"operationId": "DeleteMixin7",
|
||||
"operationId": "DeleteMixin8",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
|
|
@ -1390,7 +1499,7 @@
|
|||
"SettingsService"
|
||||
],
|
||||
"summary": "Get returns Argo CD settings",
|
||||
"operationId": "Get",
|
||||
"operationId": "GetMixin5",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
|
|
@ -3145,21 +3254,74 @@
|
|||
"connectionState": {
|
||||
"$ref": "#/definitions/v1alpha1ConnectionState"
|
||||
},
|
||||
"insecure": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"title": "Whether the repo is insecure"
|
||||
},
|
||||
"insecureIgnoreHostKey": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
"format": "boolean",
|
||||
"title": "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"title": "Password for authenticating at the repo server"
|
||||
},
|
||||
"repo": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"title": "URL of the repo"
|
||||
},
|
||||
"sshPrivateKey": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"title": "SSH private key data for authenticating at the repo server"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"title": "Username for authenticating at the repo server"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1RepositoryCertificate": {
|
||||
"type": "object",
|
||||
"title": "A RepositoryCertificate is either SSH known hosts entry or TLS certificate",
|
||||
"properties": {
|
||||
"certdata": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"title": "Actual certificate data, protocol dependent"
|
||||
},
|
||||
"certfingerprint": {
|
||||
"type": "string",
|
||||
"title": "Certificate fingerprint"
|
||||
},
|
||||
"cipher": {
|
||||
"type": "string",
|
||||
"title": "The sub type of the cert, i.e. \"ssh-rsa\""
|
||||
},
|
||||
"servername": {
|
||||
"type": "string",
|
||||
"title": "Name of the server the certificate is intended for"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"title": "Type of certificate - currently \"https\" or \"ssh\""
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1RepositoryCertificateList": {
|
||||
"type": "object",
|
||||
"title": "RepositoryCertificateList is a collection of RepositoryCertificates",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"title": "List of certificates to be processed",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v1alpha1RepositoryCertificate"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"$ref": "#/definitions/v1ListMeta"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
305
cmd/argocd/commands/cert.go
Normal file
305
cmd/argocd/commands/cert.go
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/argoproj/argo-cd/errors"
|
||||
argocdclient "github.com/argoproj/argo-cd/pkg/apiclient"
|
||||
certificatepkg "github.com/argoproj/argo-cd/pkg/apiclient/certificate"
|
||||
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/util"
|
||||
certutil "github.com/argoproj/argo-cd/util/cert"
|
||||
|
||||
"crypto/x509"
|
||||
)
|
||||
|
||||
// NewCertCommand returns a new instance of an `argocd repo` command
|
||||
func NewCertCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var command = &cobra.Command{
|
||||
Use: "cert",
|
||||
Short: "Manage repository certificates and SSH known hosts entries",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
},
|
||||
}
|
||||
|
||||
command.AddCommand(NewCertAddSSHCommand(clientOpts))
|
||||
command.AddCommand(NewCertAddTLSCommand(clientOpts))
|
||||
command.AddCommand(NewCertListCommand(clientOpts))
|
||||
command.AddCommand(NewCertRemoveCommand(clientOpts))
|
||||
return command
|
||||
}
|
||||
|
||||
func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
fromFile string
|
||||
upsert bool
|
||||
)
|
||||
var command = &cobra.Command{
|
||||
Use: "add-tls SERVERNAME",
|
||||
Short: "Add TLS certificate data for connecting to repository server SERVERNAME",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
conn, certIf := argocdclient.NewClientOrDie(clientOpts).NewCertClientOrDie()
|
||||
defer util.Close(conn)
|
||||
|
||||
if len(args) != 1 {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var certificateArray []string
|
||||
var err error
|
||||
|
||||
if fromFile != "" {
|
||||
fmt.Printf("Reading TLS certificate data in PEM format from '%s'\n", fromFile)
|
||||
certificateArray, err = certutil.ParseTLSCertificatesFromPath(fromFile)
|
||||
} else {
|
||||
fmt.Println("Enter TLS certificate data in PEM format. Press CTRL-D when finished.")
|
||||
certificateArray, err = certutil.ParseTLSCertificatesFromStream(os.Stdin)
|
||||
}
|
||||
|
||||
errors.CheckError(err)
|
||||
|
||||
certificateList := make([]appsv1.RepositoryCertificate, 0)
|
||||
|
||||
subjectMap := make(map[string]*x509.Certificate)
|
||||
|
||||
for _, entry := range certificateArray {
|
||||
// We want to make sure to only send valid certificate data to the
|
||||
// server, so we decode the certificate into X509 structure before
|
||||
// further processing it.
|
||||
x509cert, err := certutil.DecodePEMCertificateToX509(entry)
|
||||
errors.CheckError(err)
|
||||
|
||||
// TODO: We need a better way to detect duplicates sent in the stream,
|
||||
// maybe by using fingerprints? For now, no two certs with the same
|
||||
// subject may be sent.
|
||||
if subjectMap[x509cert.Subject.String()] != nil {
|
||||
fmt.Printf("ERROR: Cert with subject '%s' already seen in the input stream.\n", x509cert.Subject.String())
|
||||
continue
|
||||
} else {
|
||||
subjectMap[x509cert.Subject.String()] = x509cert
|
||||
}
|
||||
}
|
||||
|
||||
serverName := args[0]
|
||||
|
||||
if len(certificateArray) > 0 {
|
||||
certificateList = append(certificateList, appsv1.RepositoryCertificate{
|
||||
ServerName: serverName,
|
||||
CertType: "https",
|
||||
CertData: []byte(strings.Join(certificateArray, "\n")),
|
||||
})
|
||||
certificates, err := certIf.Create(context.Background(), &certificatepkg.RepositoryCertificateCreateRequest{
|
||||
Certificates: &appsv1.RepositoryCertificateList{
|
||||
Items: certificateList,
|
||||
},
|
||||
Upsert: upsert,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Created entry with %d PEM certificates for repository server %s\n", len(certificates.Items), serverName)
|
||||
} else {
|
||||
fmt.Printf("No valid certificates have been detected in the stream.\n")
|
||||
}
|
||||
},
|
||||
}
|
||||
command.Flags().StringVar(&fromFile, "from", "", "read TLS certificate data from file (default is to read from stdin)")
|
||||
command.Flags().BoolVar(&upsert, "upsert", false, "Replace existing TLS certificate if certificate is different in input")
|
||||
return command
|
||||
}
|
||||
|
||||
// NewCertAddCommand returns a new instance of an `argocd cert add` command
|
||||
func NewCertAddSSHCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
fromFile string
|
||||
batchProcess bool
|
||||
upsert bool
|
||||
certificates []appsv1.RepositoryCertificate
|
||||
)
|
||||
|
||||
var command = &cobra.Command{
|
||||
Use: "add-ssh --batch",
|
||||
Short: "Add SSH known host entries for repository servers",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
|
||||
conn, certIf := argocdclient.NewClientOrDie(clientOpts).NewCertClientOrDie()
|
||||
defer util.Close(conn)
|
||||
|
||||
var sshKnownHostsLists []string
|
||||
var err error
|
||||
|
||||
// --batch is a flag, but it is mandatory for now.
|
||||
if batchProcess {
|
||||
if fromFile != "" {
|
||||
fmt.Printf("Reading SSH known hosts entries from file '%s'\n", fromFile)
|
||||
sshKnownHostsLists, err = certutil.ParseSSHKnownHostsFromPath(fromFile)
|
||||
} else {
|
||||
fmt.Println("Enter SSH known hosts entries, one per line. Press CTRL-D when finished.")
|
||||
sshKnownHostsLists, err = certutil.ParseSSHKnownHostsFromStream(os.Stdin)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("You need to specify --batch or specify --help for usage instructions")
|
||||
}
|
||||
|
||||
errors.CheckError(err)
|
||||
|
||||
if len(sshKnownHostsLists) == 0 {
|
||||
errors.CheckError(fmt.Errorf("No valid SSH known hosts data found."))
|
||||
}
|
||||
|
||||
for _, knownHostsEntry := range sshKnownHostsLists {
|
||||
hostname, certSubType, certData, err := certutil.TokenizeSSHKnownHostsEntry(knownHostsEntry)
|
||||
errors.CheckError(err)
|
||||
_, _, err = certutil.KnownHostsLineToPublicKey(knownHostsEntry)
|
||||
errors.CheckError(err)
|
||||
certificate := appsv1.RepositoryCertificate{
|
||||
ServerName: hostname,
|
||||
CertType: "ssh",
|
||||
CertSubType: certSubType,
|
||||
CertData: certData,
|
||||
}
|
||||
|
||||
certificates = append(certificates, certificate)
|
||||
}
|
||||
|
||||
certList := &appsv1.RepositoryCertificateList{Items: certificates}
|
||||
response, err := certIf.Create(context.Background(), &certificatepkg.RepositoryCertificateCreateRequest{
|
||||
Certificates: certList,
|
||||
Upsert: upsert,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Successfully created %d SSH known host entries\n", len(response.Items))
|
||||
},
|
||||
}
|
||||
command.Flags().StringVar(&fromFile, "from", "", "Read SSH known hosts data from file (default is to read from stdin)")
|
||||
command.Flags().BoolVar(&batchProcess, "batch", false, "Perform batch processing by reading in SSH known hosts data (mandatory flag)")
|
||||
command.Flags().BoolVar(&upsert, "upsert", false, "Replace existing SSH server public host keys if key is different in input")
|
||||
return command
|
||||
}
|
||||
|
||||
// NewCertRemoveCommand returns a new instance of an `argocd cert rm` command
|
||||
func NewCertRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
removeAllCerts bool
|
||||
certType string
|
||||
certSubType string
|
||||
certQuery certificatepkg.RepositoryCertificateQuery
|
||||
)
|
||||
var command = &cobra.Command{
|
||||
Use: "rm REPOSERVER",
|
||||
Short: "Remove certificate of TYPE for REPOSERVER",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
if len(args) < 1 && !removeAllCerts {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
conn, certIf := argocdclient.NewClientOrDie(clientOpts).NewCertClientOrDie()
|
||||
defer util.Close(conn)
|
||||
if removeAllCerts {
|
||||
certQuery = certificatepkg.RepositoryCertificateQuery{
|
||||
HostNamePattern: "*",
|
||||
CertType: "*",
|
||||
CertSubType: "*",
|
||||
}
|
||||
} else {
|
||||
certQuery = certificatepkg.RepositoryCertificateQuery{
|
||||
HostNamePattern: args[0],
|
||||
CertType: certType,
|
||||
CertSubType: certSubType,
|
||||
}
|
||||
}
|
||||
removed, err := certIf.Delete(context.Background(), &certQuery)
|
||||
errors.CheckError(err)
|
||||
if len(removed.Items) > 0 {
|
||||
for _, cert := range removed.Items {
|
||||
fmt.Printf("Removed cert for '%s' of type '%s' (subtype '%s')\n", cert.ServerName, cert.CertType, cert.CertSubType)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("No certificates were removed (none matched the given patterns)")
|
||||
}
|
||||
},
|
||||
}
|
||||
command.Flags().BoolVar(&removeAllCerts, "remove-all", false, "Remove all configured certificates of all types from server (DANGER: use with care!)")
|
||||
command.Flags().StringVar(&certType, "cert-type", "", "Only remove certs of given type (ssh, https)")
|
||||
command.Flags().StringVar(&certSubType, "cert-sub-type", "", "Only remove certs of given sub-type (only for ssh)")
|
||||
return command
|
||||
}
|
||||
|
||||
// NewCertListCommand returns a new instance of an `argocd cert rm` command
|
||||
func NewCertListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
certType string
|
||||
hostNamePattern string
|
||||
sortOrder string
|
||||
)
|
||||
var command = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List configured certificates",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
if certType != "" {
|
||||
switch certType {
|
||||
case "ssh":
|
||||
case "https":
|
||||
default:
|
||||
fmt.Println("cert-type must be either ssh or https")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
conn, certIf := argocdclient.NewClientOrDie(clientOpts).NewCertClientOrDie()
|
||||
defer util.Close(conn)
|
||||
certificates, err := certIf.List(context.Background(), &certificatepkg.RepositoryCertificateQuery{HostNamePattern: hostNamePattern, CertType: certType})
|
||||
errors.CheckError(err)
|
||||
printCertTable(certificates.Items, sortOrder)
|
||||
},
|
||||
}
|
||||
|
||||
command.Flags().StringVar(&sortOrder, "sort", "", "set display sort order, valid: 'hostname', 'type'")
|
||||
command.Flags().StringVar(&certType, "cert-type", "", "only list certificates of given type, valid: 'ssh','https'")
|
||||
command.Flags().StringVar(&hostNamePattern, "hostname-pattern", "", "only list certificates for hosts matching given glob-pattern")
|
||||
return command
|
||||
}
|
||||
|
||||
// Print table of certificate info
|
||||
func printCertTable(certs []appsv1.RepositoryCertificate, sortOrder string) {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "HOSTNAME\tTYPE\tSUBTYPE\tFINGERPRINT/SUBJECT\n")
|
||||
|
||||
if sortOrder == "hostname" || sortOrder == "" {
|
||||
sort.Slice(certs, func(i, j int) bool {
|
||||
return certs[i].ServerName < certs[j].ServerName
|
||||
})
|
||||
} else if sortOrder == "type" {
|
||||
sort.Slice(certs, func(i, j int) bool {
|
||||
return certs[i].CertType < certs[j].CertType
|
||||
})
|
||||
}
|
||||
|
||||
for _, c := range certs {
|
||||
if c.CertType == "ssh" {
|
||||
_, pubKey, err := certutil.TokenizedDataToPublicKey(c.ServerName, c.CertSubType, string(c.CertData))
|
||||
errors.CheckError(err)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\tSHA256:%s\n", c.ServerName, c.CertType, c.CertSubType, certutil.SSHFingerprintSHA256(pubKey))
|
||||
} else if c.CertType == "https" {
|
||||
x509Data, err := certutil.DecodePEMCertificateToX509(string(c.CertData))
|
||||
var subject string
|
||||
keyType := "-?-"
|
||||
if err != nil {
|
||||
subject = err.Error()
|
||||
} else {
|
||||
subject = x509Data.Subject.String()
|
||||
keyType = x509Data.PublicKeyAlgorithm.String()
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", c.ServerName, c.CertType, strings.ToLower(keyType), subject)
|
||||
}
|
||||
}
|
||||
_ = w.Flush()
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ import (
|
|||
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/util"
|
||||
"github.com/argoproj/argo-cd/util/cli"
|
||||
"github.com/argoproj/argo-cd/util/git"
|
||||
)
|
||||
|
||||
// NewRepoCommand returns a new instance of an `argocd repo` command
|
||||
|
|
@ -39,10 +38,11 @@ func NewRepoCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
|||
// NewRepoAddCommand returns a new instance of an `argocd repo add` command
|
||||
func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
repo appsv1.Repository
|
||||
upsert bool
|
||||
sshPrivateKeyPath string
|
||||
insecureIgnoreHostKey bool
|
||||
repo appsv1.Repository
|
||||
upsert bool
|
||||
sshPrivateKeyPath string
|
||||
insecureIgnoreHostKey bool
|
||||
insecureSkipServerVerification bool
|
||||
)
|
||||
var command = &cobra.Command{
|
||||
Use: "add REPO",
|
||||
|
|
@ -60,24 +60,32 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
|||
}
|
||||
repo.SSHPrivateKey = string(keyData)
|
||||
}
|
||||
// InsecureIgnoreHostKey is deprecated and only here for backwards compat
|
||||
repo.InsecureIgnoreHostKey = insecureIgnoreHostKey
|
||||
// First test the repo *without* username/password. This gives us a hint on whether this
|
||||
// is a private repo.
|
||||
// NOTE: it is important not to run git commands to test git credentials on the user's
|
||||
// system since it may mess with their git credential store (e.g. osx keychain).
|
||||
// See issue #315
|
||||
err := git.TestRepo(repo.Repo, "", "", repo.SSHPrivateKey, repo.InsecureIgnoreHostKey)
|
||||
if err != nil {
|
||||
if yes, _ := git.IsSSHURL(repo.Repo); yes {
|
||||
// If we failed using git SSH credentials, then the repo is automatically bad
|
||||
log.Fatal(err)
|
||||
}
|
||||
// If we can't test the repo, it's probably private. Prompt for credentials and
|
||||
// let the server test it.
|
||||
repo.Username, repo.Password = cli.PromptCredentials(repo.Username, repo.Password)
|
||||
}
|
||||
repo.Insecure = insecureSkipServerVerification
|
||||
|
||||
conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie()
|
||||
defer util.Close(conn)
|
||||
|
||||
// If the user set a username, but didn't supply password via --password,
|
||||
// then we prompt for it
|
||||
if repo.Username != "" && repo.Password == "" {
|
||||
repo.Password = cli.PromptPassword(repo.Password)
|
||||
}
|
||||
|
||||
// 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.
|
||||
repoAccessReq := repositorypkg.RepoAccessQuery{
|
||||
Repo: repo.Repo,
|
||||
Username: repo.Username,
|
||||
Password: repo.Password,
|
||||
SshPrivateKey: repo.SSHPrivateKey,
|
||||
Insecure: (repo.InsecureIgnoreHostKey || repo.Insecure),
|
||||
}
|
||||
_, err := repoIf.ValidateAccess(context.Background(), &repoAccessReq)
|
||||
errors.CheckError(err)
|
||||
|
||||
repoCreateReq := repositorypkg.RepoCreateRequest{
|
||||
Repo: &repo,
|
||||
Upsert: upsert,
|
||||
|
|
@ -90,7 +98,8 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
|||
command.Flags().StringVar(&repo.Username, "username", "", "username to the repository")
|
||||
command.Flags().StringVar(&repo.Password, "password", "", "password to the repository")
|
||||
command.Flags().StringVar(&sshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")
|
||||
command.Flags().BoolVar(&insecureIgnoreHostKey, "insecure-ignore-host-key", false, "disables SSH strict host key checking")
|
||||
command.Flags().BoolVar(&insecureIgnoreHostKey, "insecure-ignore-host-key", false, "disables SSH strict host key checking (deprecated, use --insecure-skip-server-validation instead)")
|
||||
command.Flags().BoolVar(&insecureSkipServerVerification, "insecure-skip-server-verification", false, "disables server certificate and host key checks")
|
||||
command.Flags().BoolVar(&upsert, "upsert", false, "Override an existing repository with the same name even if the spec differs")
|
||||
return command
|
||||
}
|
||||
|
|
@ -119,9 +128,15 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
|||
// Print table of repo info
|
||||
func printRepoTable(repos []appsv1.Repository) {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "REPO\tUSER\tSTATUS\tMESSAGE\n")
|
||||
fmt.Fprintf(w, "REPO\tINSECURE\tUSER\tSTATUS\tMESSAGE\n")
|
||||
for _, r := range repos {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", r.Repo, r.Username, r.ConnectionState.Status, r.ConnectionState.Message)
|
||||
var username string
|
||||
if r.Username == "" {
|
||||
username = "-"
|
||||
} else {
|
||||
username = r.Username
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%v\t%s\t%s\t%s\n", r.Repo, r.Insecure, username, r.ConnectionState.Status, r.ConnectionState.Message)
|
||||
}
|
||||
_ = w.Flush()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ func NewCommand() *cobra.Command {
|
|||
command.AddCommand(NewProjectCommand(&clientOpts))
|
||||
command.AddCommand(NewAccountCommand(&clientOpts))
|
||||
command.AddCommand(NewLogoutCommand(&clientOpts))
|
||||
command.AddCommand(NewCertCommand(&clientOpts))
|
||||
|
||||
defaultLocalConfigPath, err := localconfig.DefaultLocalConfigPath()
|
||||
errors.CheckError(err)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ const (
|
|||
ArgoCDConfigMapName = "argocd-cm"
|
||||
ArgoCDSecretName = "argocd-secret"
|
||||
ArgoCDRBACConfigMapName = "argocd-rbac-cm"
|
||||
// Contains SSH known hosts data for connecting repositories. Will get mounted as volume to pods
|
||||
ArgoCDKnownHostsConfigMapName = "argocd-ssh-known-hosts-cm"
|
||||
// Contains TLS certificate data for connecting repositories. Will get mounted as volume to pods
|
||||
ArgoCDTLSCertsConfigMapName = "argocd-tls-certs-cm"
|
||||
)
|
||||
|
||||
// Default system namespace
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ func newFakeController(data *fakeData) *ApplicationController {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: test.FakeArgoCDNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: nil,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,54 @@ argocd repo add git@github.com:argoproj/argocd-example-apps.git --ssh-private-ke
|
|||
|
||||
## Self-signed & Untrusted TLS Certificates
|
||||
|
||||
> v1.2 or higher
|
||||
|
||||
If you are connecting a repository on a HTTPS server using a self-signed certificate, or a certificate signed by a custom Certificate Authority (CA) which are not known to ArgoCD, the repository will not be added due to security reasons. This is indicated by an error message such as `x509: certificate signed by unknown authority`.
|
||||
|
||||
1. You can let ArgoCD connect the repository in an insecure way, without verifying the server's certificate at all. This can be accomplished by using the `--insecure-repository` flag when adding the repository with the `argocd` CLI utility. However, this should be done only for non-production setups, as it imposes a serious security issue through possible man-in-the-middle attacks.
|
||||
|
||||
2. You can let ArgoCD use a custom certificate for the verification of the server's certificate using the `cert add-tls` command of the `argocd` CLI utility. This is the recommended method and suitable for production use. In order to do so, you will need the server's certificate, or the certificate of the CA used to sign the server's certificate, in PEM format.
|
||||
|
||||
!!! note
|
||||
For invalid server certificates, such as those without matching server name, or those that are expired, adding a CA certificate will not help. In this case, your only option will be to use the `--insecure-repository` flag to connect the repository. You are strongly urged to use a valid certificate on the repository server, or to urge the server's administrator to replace the faulty certificate with a valid one.
|
||||
|
||||
Example for adding a HTTPS repository to ArgoCD without verifying the server's certificate (**Caution:** This is **not** recommended for production use):
|
||||
|
||||
```bash
|
||||
argocd repo add --insecure-repository https://git.example.com/test-repo
|
||||
```
|
||||
|
||||
Example for adding a CA certificate contained in file `~/myca-cert.pem` to properly verify the repository server:
|
||||
|
||||
```bash
|
||||
argocd cert add-tls git.example.com --from ~/myca-cert.pem
|
||||
argocd repo add https://git.example.com/test-repo
|
||||
```
|
||||
|
||||
You can also add more than one PEM for a server by concatenating them into the input stream. This might be useful if the repository server is about to replace the server certificate, possibly with one signed by a different CA. This way, you can have the old (current) as well as the new (future) certificate co-existing. If you already have the old certificate configured, use the `--upsert` flag and add the old and the new one in a single run:
|
||||
|
||||
```bash
|
||||
cat cert1.pem cert2.pem | argocd cert add-tls git.example.com --upsert
|
||||
```
|
||||
|
||||
!!! note
|
||||
You can add multiple TLS certificates for a single server by either using a file containing multiple PEM certificates, or by using the `--append` flag to the `cert add-tls` command of the CLI.
|
||||
|
||||
!!! note
|
||||
To replace an existing certificate for a server, use the `--upsert` flag to the `cert add-tls` CLI command.
|
||||
|
||||
!!! note
|
||||
TLS certificates are configured on a per-server, not on a per-repository basis. If you connect multiple repositories from the same server, you only have to configure the certificates once for this server.
|
||||
|
||||
!!! note
|
||||
It can take up to a couple of minutes until the changes performed by the `argocd cert` command are propagated across your cluster, depending on your Kubernetes setup.
|
||||
|
||||
You can also manage TLS certificates in a declarative, self-managed ArgoCD setup. All TLS certificates are stored in the ConfigMap object `argocd-tls-cert-cm`.
|
||||
|
||||
Managing TLS certificates via the web UI is currently not possible.
|
||||
|
||||
> Before v1.2
|
||||
|
||||
We do not currently have first-class support for this. See [#1513](https://github.com/argoproj/argo-cd/issues/1513).
|
||||
|
||||
As a work-around, you can customize your Argo CD image. See [#1344](https://github.com/argoproj/argo-cd/issues/1344#issuecomment-479811810)
|
||||
|
|
@ -50,6 +98,35 @@ As a work-around, you can customize your Argo CD image. See [#1344](https://gith
|
|||
## Unknown SSH Hosts
|
||||
|
||||
If you are using a privately hosted Git service over SSH, then you have the following options:
|
||||
|
||||
> v1.2 or later
|
||||
|
||||
1. You can let ArgoCD connect the repository in an insecure way, without verifying the server's SSH host key at all. This can be accomplished by using the `--insecure-repository` flag when adding the repository with the `argocd` CLI utility. However, this should be done only for non-production setups, as it imposes a serious security issue through possible man-in-the-middle attacks.
|
||||
|
||||
2. You can make the server's SSH public key known to ArgoCD by using the `cert add-ssh` command of the `argocd` CLI utility. This is the recommended method and suitable for production use. In order to do so, you will need the server's SSH public host key, in the `known_hosts` format understood by `ssh`. You can get the server's public SSH host key e.g. by using the `ssh-keyscan` utility.
|
||||
|
||||
Example for adding all available SSH public host keys for a server to ArgoCD:
|
||||
|
||||
```bash
|
||||
ssh-keyscan server.example.com | argocd cert add-ssh --batch
|
||||
|
||||
```
|
||||
|
||||
Example for importing an existing `known_hosts` file to ArgoCD:
|
||||
|
||||
```bash
|
||||
argocd cert add-ssh --batch --from /etc/ssh/ssh_known_hosts
|
||||
```
|
||||
|
||||
!!! note
|
||||
It can take up to a couple of minutes until the changes performed by the `argocd cert` command are propagated across your cluster, depending on your Kubernetes setup.
|
||||
|
||||
You can also manage SSH known hosts entries in a declarative, self-managed ArgoCD setup. All SSH public host keys are stored in the ConfigMap object `argocd-ssh-known-hosts-cm`.
|
||||
|
||||
Managing SSH public host keys via the web UI is currently not possible.
|
||||
|
||||
> Before v1.2
|
||||
|
||||
|
||||
(1) You can customize the Argo CD Docker image by adding the host's SSH public key to `/etc/ssh/ssh_known_hosts`. Additional entries to this file can be generated using the `ssh-keyscan` utility (e.g. `ssh-keyscan your-private-git-server.com`. For more information see [example](https://github.com/argoproj/argo-cd/tree/master/examples/known-hosts) which demonstrates how `/etc/ssh/ssh_known_hosts` can be customized.
|
||||
|
||||
|
|
@ -71,5 +148,5 @@ argocd repo add git@github.com:argoproj/argocd-example-apps.git --ssh-private-ke
|
|||
|
||||
## Declarative Configuration
|
||||
|
||||
See [declarative setup](../operator-manual/declarative-setup#Repositories)
|
||||
See [declarative setup](../../operator-manual/declarative-setup#Repositories)
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ clean_swagger() {
|
|||
/usr/bin/find "${SWAGGER_ROOT}" -name '*.swagger.json' -delete
|
||||
}
|
||||
|
||||
collect_swagger server 26
|
||||
collect_swagger server 27
|
||||
clean_swagger server
|
||||
clean_swagger reposerver
|
||||
clean_swagger controller
|
||||
|
|
|
|||
16
manifests/base/config/argocd-ssh-known-hosts-cm.yaml
Normal file
16
manifests/base/config/argocd-ssh-known-hosts-cm.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-ssh-known-hosts-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
8
manifests/base/config/argocd-tls-certs-cm.yaml
Normal file
8
manifests/base/config/argocd-tls-certs-cm.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-tls-certs-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-tls-certs-cm
|
||||
data:
|
||||
|
|
@ -4,4 +4,6 @@ kind: Kustomization
|
|||
resources:
|
||||
- argocd-cm.yaml
|
||||
- argocd-secret.yaml
|
||||
- argocd-rbac-cm.yaml
|
||||
- argocd-rbac-cm.yaml
|
||||
- argocd-ssh-known-hosts-cm.yaml
|
||||
- argocd-tls-certs-cm.yaml
|
||||
|
|
|
|||
|
|
@ -37,3 +37,15 @@ spec:
|
|||
port: 8081
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: ssh-known-hosts
|
||||
mountPath: /app/config/ssh
|
||||
- name: tls-certs
|
||||
mountPath: /app/config/tls
|
||||
volumes:
|
||||
- name: ssh-known-hosts
|
||||
configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
- name: tls-certs
|
||||
configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ spec:
|
|||
volumeMounts:
|
||||
- mountPath: /shared
|
||||
name: static-files
|
||||
- name: ssh-known-hosts
|
||||
mountPath: /app/config/ssh
|
||||
- name: tls-certs
|
||||
mountPath: /app/config/tls
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
- containerPort: 8083
|
||||
|
|
@ -50,3 +54,9 @@ spec:
|
|||
volumes:
|
||||
- emptyDir: {}
|
||||
name: static-files
|
||||
- name: ssh-known-hosts
|
||||
configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
- name: tls-certs
|
||||
configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
|
|
|
|||
|
|
@ -2720,6 +2720,32 @@ metadata:
|
|||
name: argocd-redis-ha-probes
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-ssh-known-hosts-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data: null
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-tls-certs-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-tls-certs-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
|
|
@ -3086,6 +3112,18 @@ spec:
|
|||
periodSeconds: 10
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
volumeMounts:
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
|
@ -3153,6 +3191,10 @@ spec:
|
|||
volumeMounts:
|
||||
- mountPath: /shared
|
||||
name: static-files
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
initContainers:
|
||||
- command:
|
||||
- cp
|
||||
|
|
@ -3169,6 +3211,12 @@ spec:
|
|||
volumes:
|
||||
- emptyDir: {}
|
||||
name: static-files
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
|
|
|
|||
|
|
@ -2635,6 +2635,32 @@ metadata:
|
|||
name: argocd-redis-ha-probes
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-ssh-known-hosts-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data: null
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-tls-certs-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-tls-certs-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
|
|
@ -3001,6 +3027,18 @@ spec:
|
|||
periodSeconds: 10
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
volumeMounts:
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
|
@ -3068,6 +3106,10 @@ spec:
|
|||
volumeMounts:
|
||||
- mountPath: /shared
|
||||
name: static-files
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
initContainers:
|
||||
- command:
|
||||
- cp
|
||||
|
|
@ -3084,6 +3126,12 @@ spec:
|
|||
volumes:
|
||||
- emptyDir: {}
|
||||
name: static-files
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
|
|
|
|||
|
|
@ -2578,6 +2578,32 @@ metadata:
|
|||
name: argocd-rbac-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-ssh-known-hosts-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data: null
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-tls-certs-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-tls-certs-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
|
|
@ -2858,6 +2884,18 @@ spec:
|
|||
periodSeconds: 10
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
volumeMounts:
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
|
@ -2902,6 +2940,10 @@ spec:
|
|||
volumeMounts:
|
||||
- mountPath: /shared
|
||||
name: static-files
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
initContainers:
|
||||
- command:
|
||||
- cp
|
||||
|
|
@ -2918,3 +2960,9 @@ spec:
|
|||
volumes:
|
||||
- emptyDir: {}
|
||||
name: static-files
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
|
|
|
|||
|
|
@ -2493,6 +2493,32 @@ metadata:
|
|||
name: argocd-rbac-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-ssh-known-hosts-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data: null
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-tls-certs-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-tls-certs-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
|
|
@ -2773,6 +2799,18 @@ spec:
|
|||
periodSeconds: 10
|
||||
tcpSocket:
|
||||
port: 8081
|
||||
volumeMounts:
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
|
@ -2817,6 +2855,10 @@ spec:
|
|||
volumeMounts:
|
||||
- mountPath: /shared
|
||||
name: static-files
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
- mountPath: /app/config/tls
|
||||
name: tls-certs
|
||||
initContainers:
|
||||
- command:
|
||||
- cp
|
||||
|
|
@ -2833,3 +2875,9 @@ spec:
|
|||
volumes:
|
||||
- emptyDir: {}
|
||||
name: static-files
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
name: ssh-known-hosts
|
||||
- configMap:
|
||||
name: argocd-tls-certs-cm
|
||||
name: tls-certs
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/argoproj/argo-cd/common"
|
||||
accountpkg "github.com/argoproj/argo-cd/pkg/apiclient/account"
|
||||
applicationpkg "github.com/argoproj/argo-cd/pkg/apiclient/application"
|
||||
certificatepkg "github.com/argoproj/argo-cd/pkg/apiclient/certificate"
|
||||
clusterpkg "github.com/argoproj/argo-cd/pkg/apiclient/cluster"
|
||||
projectpkg "github.com/argoproj/argo-cd/pkg/apiclient/project"
|
||||
repositorypkg "github.com/argoproj/argo-cd/pkg/apiclient/repository"
|
||||
|
|
@ -58,6 +59,8 @@ type Client interface {
|
|||
OIDCConfig(context.Context, *settingspkg.Settings) (*oauth2.Config, *oidc.Provider, error)
|
||||
NewRepoClient() (io.Closer, repositorypkg.RepositoryServiceClient, error)
|
||||
NewRepoClientOrDie() (io.Closer, repositorypkg.RepositoryServiceClient)
|
||||
NewCertClient() (io.Closer, certificatepkg.CertificateServiceClient, error)
|
||||
NewCertClientOrDie() (io.Closer, certificatepkg.CertificateServiceClient)
|
||||
NewClusterClient() (io.Closer, clusterpkg.ClusterServiceClient, error)
|
||||
NewClusterClientOrDie() (io.Closer, clusterpkg.ClusterServiceClient)
|
||||
NewApplicationClient() (io.Closer, applicationpkg.ApplicationServiceClient, error)
|
||||
|
|
@ -437,6 +440,23 @@ func (c *client) NewRepoClientOrDie() (io.Closer, repositorypkg.RepositoryServic
|
|||
return conn, repoIf
|
||||
}
|
||||
|
||||
func (c *client) NewCertClient() (io.Closer, certificatepkg.CertificateServiceClient, error) {
|
||||
conn, closer, err := c.newConn()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
certIf := certificatepkg.NewCertificateServiceClient(conn)
|
||||
return closer, certIf, nil
|
||||
}
|
||||
|
||||
func (c *client) NewCertClientOrDie() (io.Closer, certificatepkg.CertificateServiceClient) {
|
||||
conn, certIf, err := c.NewCertClient()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to establish connection to %s: %v", c.ServerAddr, err)
|
||||
}
|
||||
return conn, certIf
|
||||
}
|
||||
|
||||
func (c *client) NewClusterClient() (io.Closer, clusterpkg.ClusterServiceClient, error) {
|
||||
conn, closer, err := c.newConn()
|
||||
if err != nil {
|
||||
|
|
|
|||
949
pkg/apiclient/certificate/certificate.pb.go
Normal file
949
pkg/apiclient/certificate/certificate.pb.go
Normal file
|
|
@ -0,0 +1,949 @@
|
|||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: server/certificate/certificate.proto
|
||||
|
||||
package certificate // import "github.com/argoproj/argo-cd/pkg/apiclient/certificate"
|
||||
|
||||
/*
|
||||
Certificate Service
|
||||
|
||||
Certificate Service API performs CRUD actions against repository certificate
|
||||
resources.
|
||||
*/
|
||||
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Message to query the server for configured repository certificates
|
||||
type RepositoryCertificateQuery struct {
|
||||
// A file-glob pattern (not regular expression) the host name has to match
|
||||
HostNamePattern string `protobuf:"bytes,1,opt,name=hostNamePattern,proto3" json:"hostNamePattern,omitempty"`
|
||||
// The type of the certificate to match (ssh or https)
|
||||
CertType string `protobuf:"bytes,2,opt,name=certType,proto3" json:"certType,omitempty"`
|
||||
// The sub type of the certificate to match (protocol dependent, usually only used for ssh certs)
|
||||
CertSubType string `protobuf:"bytes,3,opt,name=certSubType,proto3" json:"certSubType,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateQuery) Reset() { *m = RepositoryCertificateQuery{} }
|
||||
func (m *RepositoryCertificateQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepositoryCertificateQuery) ProtoMessage() {}
|
||||
func (*RepositoryCertificateQuery) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_certificate_7cceab803f50bba4, []int{0}
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_RepositoryCertificateQuery.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *RepositoryCertificateQuery) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RepositoryCertificateQuery.Merge(dst, src)
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RepositoryCertificateQuery.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RepositoryCertificateQuery proto.InternalMessageInfo
|
||||
|
||||
func (m *RepositoryCertificateQuery) GetHostNamePattern() string {
|
||||
if m != nil {
|
||||
return m.HostNamePattern
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateQuery) GetCertType() string {
|
||||
if m != nil {
|
||||
return m.CertType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateQuery) GetCertSubType() string {
|
||||
if m != nil {
|
||||
return m.CertSubType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Request to create a set of certificates
|
||||
type RepositoryCertificateCreateRequest struct {
|
||||
// List of certificates to be created
|
||||
Certificates *v1alpha1.RepositoryCertificateList `protobuf:"bytes,1,opt,name=certificates" json:"certificates,omitempty"`
|
||||
// Whether to upsert already existing certificates
|
||||
Upsert bool `protobuf:"varint,2,opt,name=upsert,proto3" json:"upsert,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) Reset() { *m = RepositoryCertificateCreateRequest{} }
|
||||
func (m *RepositoryCertificateCreateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepositoryCertificateCreateRequest) ProtoMessage() {}
|
||||
func (*RepositoryCertificateCreateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_certificate_7cceab803f50bba4, []int{1}
|
||||
}
|
||||
func (m *RepositoryCertificateCreateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *RepositoryCertificateCreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_RepositoryCertificateCreateRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *RepositoryCertificateCreateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RepositoryCertificateCreateRequest.Merge(dst, src)
|
||||
}
|
||||
func (m *RepositoryCertificateCreateRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *RepositoryCertificateCreateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RepositoryCertificateCreateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RepositoryCertificateCreateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) GetCertificates() *v1alpha1.RepositoryCertificateList {
|
||||
if m != nil {
|
||||
return m.Certificates
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) GetUpsert() bool {
|
||||
if m != nil {
|
||||
return m.Upsert
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RepositoryCertificateResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateResponse) Reset() { *m = RepositoryCertificateResponse{} }
|
||||
func (m *RepositoryCertificateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepositoryCertificateResponse) ProtoMessage() {}
|
||||
func (*RepositoryCertificateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_certificate_7cceab803f50bba4, []int{2}
|
||||
}
|
||||
func (m *RepositoryCertificateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *RepositoryCertificateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_RepositoryCertificateResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *RepositoryCertificateResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RepositoryCertificateResponse.Merge(dst, src)
|
||||
}
|
||||
func (m *RepositoryCertificateResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *RepositoryCertificateResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RepositoryCertificateResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RepositoryCertificateResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*RepositoryCertificateQuery)(nil), "certificate.RepositoryCertificateQuery")
|
||||
proto.RegisterType((*RepositoryCertificateCreateRequest)(nil), "certificate.RepositoryCertificateCreateRequest")
|
||||
proto.RegisterType((*RepositoryCertificateResponse)(nil), "certificate.RepositoryCertificateResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for CertificateService service
|
||||
|
||||
type CertificateServiceClient interface {
|
||||
// List all available certificates
|
||||
List(ctx context.Context, in *RepositoryCertificateQuery, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error)
|
||||
// Creates the requested certificates on the server
|
||||
Create(ctx context.Context, in *RepositoryCertificateCreateRequest, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error)
|
||||
Delete(ctx context.Context, in *RepositoryCertificateQuery, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error)
|
||||
}
|
||||
|
||||
type certificateServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewCertificateServiceClient(cc *grpc.ClientConn) CertificateServiceClient {
|
||||
return &certificateServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *certificateServiceClient) List(ctx context.Context, in *RepositoryCertificateQuery, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error) {
|
||||
out := new(v1alpha1.RepositoryCertificateList)
|
||||
err := c.cc.Invoke(ctx, "/certificate.CertificateService/List", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *certificateServiceClient) Create(ctx context.Context, in *RepositoryCertificateCreateRequest, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error) {
|
||||
out := new(v1alpha1.RepositoryCertificateList)
|
||||
err := c.cc.Invoke(ctx, "/certificate.CertificateService/Create", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *certificateServiceClient) Delete(ctx context.Context, in *RepositoryCertificateQuery, opts ...grpc.CallOption) (*v1alpha1.RepositoryCertificateList, error) {
|
||||
out := new(v1alpha1.RepositoryCertificateList)
|
||||
err := c.cc.Invoke(ctx, "/certificate.CertificateService/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for CertificateService service
|
||||
|
||||
type CertificateServiceServer interface {
|
||||
// List all available certificates
|
||||
List(context.Context, *RepositoryCertificateQuery) (*v1alpha1.RepositoryCertificateList, error)
|
||||
// Creates the requested certificates on the server
|
||||
Create(context.Context, *RepositoryCertificateCreateRequest) (*v1alpha1.RepositoryCertificateList, error)
|
||||
Delete(context.Context, *RepositoryCertificateQuery) (*v1alpha1.RepositoryCertificateList, error)
|
||||
}
|
||||
|
||||
func RegisterCertificateServiceServer(s *grpc.Server, srv CertificateServiceServer) {
|
||||
s.RegisterService(&_CertificateService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _CertificateService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RepositoryCertificateQuery)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CertificateServiceServer).List(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/certificate.CertificateService/List",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CertificateServiceServer).List(ctx, req.(*RepositoryCertificateQuery))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CertificateService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RepositoryCertificateCreateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CertificateServiceServer).Create(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/certificate.CertificateService/Create",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CertificateServiceServer).Create(ctx, req.(*RepositoryCertificateCreateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CertificateService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RepositoryCertificateQuery)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CertificateServiceServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/certificate.CertificateService/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CertificateServiceServer).Delete(ctx, req.(*RepositoryCertificateQuery))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _CertificateService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "certificate.CertificateService",
|
||||
HandlerType: (*CertificateServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "List",
|
||||
Handler: _CertificateService_List_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Create",
|
||||
Handler: _CertificateService_Create_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _CertificateService_Delete_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "server/certificate/certificate.proto",
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateQuery) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateQuery) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.HostNamePattern) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintCertificate(dAtA, i, uint64(len(m.HostNamePattern)))
|
||||
i += copy(dAtA[i:], m.HostNamePattern)
|
||||
}
|
||||
if len(m.CertType) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintCertificate(dAtA, i, uint64(len(m.CertType)))
|
||||
i += copy(dAtA[i:], m.CertType)
|
||||
}
|
||||
if len(m.CertSubType) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintCertificate(dAtA, i, uint64(len(m.CertSubType)))
|
||||
i += copy(dAtA[i:], m.CertSubType)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Certificates != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintCertificate(dAtA, i, uint64(m.Certificates.Size()))
|
||||
n1, err := m.Certificates.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
}
|
||||
if m.Upsert {
|
||||
dAtA[i] = 0x10
|
||||
i++
|
||||
if m.Upsert {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintCertificate(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.HostNamePattern)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovCertificate(uint64(l))
|
||||
}
|
||||
l = len(m.CertType)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovCertificate(uint64(l))
|
||||
}
|
||||
l = len(m.CertSubType)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovCertificate(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateCreateRequest) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Certificates != nil {
|
||||
l = m.Certificates.Size()
|
||||
n += 1 + l + sovCertificate(uint64(l))
|
||||
}
|
||||
if m.Upsert {
|
||||
n += 2
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *RepositoryCertificateResponse) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovCertificate(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozCertificate(x uint64) (n int) {
|
||||
return sovCertificate(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *RepositoryCertificateQuery) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateQuery: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateQuery: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field HostNamePattern", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
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 ErrInvalidLengthCertificate
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.HostNamePattern = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CertType", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
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 ErrInvalidLengthCertificate
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.CertType = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CertSubType", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
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 ErrInvalidLengthCertificate
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.CertSubType = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCertificate(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthCertificate
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *RepositoryCertificateCreateRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateCreateRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateCreateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Certificates", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthCertificate
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Certificates == nil {
|
||||
m.Certificates = &v1alpha1.RepositoryCertificateList{}
|
||||
}
|
||||
if err := m.Certificates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Upsert", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Upsert = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCertificate(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthCertificate
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *RepositoryCertificateResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: RepositoryCertificateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCertificate(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthCertificate
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipCertificate(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthCertificate
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCertificate
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipCertificate(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthCertificate = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowCertificate = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("server/certificate/certificate.proto", fileDescriptor_certificate_7cceab803f50bba4)
|
||||
}
|
||||
|
||||
var fileDescriptor_certificate_7cceab803f50bba4 = []byte{
|
||||
// 448 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x53, 0x41, 0x6b, 0x14, 0x31,
|
||||
0x14, 0x26, 0xb5, 0x2c, 0x35, 0x15, 0x84, 0x50, 0x4a, 0x19, 0xea, 0x5a, 0x86, 0x82, 0xa5, 0x60,
|
||||
0xc2, 0x56, 0xbc, 0x78, 0x74, 0xbd, 0x08, 0x22, 0x3a, 0xed, 0xc9, 0x8b, 0x64, 0x67, 0x9f, 0xd9,
|
||||
0xd8, 0x69, 0x12, 0x93, 0x37, 0x83, 0x7b, 0x15, 0xff, 0x81, 0x7f, 0x40, 0x10, 0xff, 0x82, 0x17,
|
||||
0xff, 0x80, 0x47, 0xc1, 0x3f, 0x20, 0x8b, 0x3f, 0x44, 0x26, 0xdb, 0xda, 0x8c, 0x8c, 0xe8, 0x65,
|
||||
0xc1, 0xdb, 0xcb, 0xf7, 0x92, 0xf7, 0xbe, 0xef, 0x7b, 0x79, 0x74, 0x3f, 0x80, 0x6f, 0xc0, 0x8b,
|
||||
0x12, 0x3c, 0xea, 0x17, 0xba, 0x94, 0x08, 0x69, 0xcc, 0x9d, 0xb7, 0x68, 0xd9, 0x66, 0x02, 0x65,
|
||||
0x5b, 0xca, 0x2a, 0x1b, 0x71, 0xd1, 0x46, 0xcb, 0x2b, 0xd9, 0xae, 0xb2, 0x56, 0x55, 0x20, 0xa4,
|
||||
0xd3, 0x42, 0x1a, 0x63, 0x51, 0xa2, 0xb6, 0x26, 0x9c, 0x67, 0x1f, 0x2a, 0x8d, 0xb3, 0x7a, 0xc2,
|
||||
0x4b, 0x7b, 0x26, 0xa4, 0x8f, 0xcf, 0x5f, 0xc6, 0xe0, 0x76, 0x39, 0x15, 0xee, 0x54, 0xb5, 0xcf,
|
||||
0x82, 0x90, 0xce, 0x55, 0x6d, 0x0f, 0x6d, 0x8d, 0x68, 0x46, 0xb2, 0x72, 0x33, 0x39, 0x12, 0x0a,
|
||||
0x0c, 0x78, 0x89, 0x30, 0x5d, 0x96, 0xca, 0xdf, 0x12, 0x9a, 0x15, 0xe0, 0x6c, 0xd0, 0x68, 0xfd,
|
||||
0x7c, 0x7c, 0x49, 0xec, 0x69, 0x0d, 0x7e, 0xce, 0x0e, 0xe8, 0xf5, 0x99, 0x0d, 0xf8, 0x58, 0x9e,
|
||||
0xc1, 0x13, 0x89, 0x08, 0xde, 0xec, 0x90, 0x3d, 0x72, 0x70, 0xb5, 0xf8, 0x1d, 0x66, 0x19, 0xdd,
|
||||
0x68, 0x65, 0x9d, 0xcc, 0x1d, 0xec, 0xac, 0xc5, 0x2b, 0xbf, 0xce, 0x6c, 0x8f, 0x46, 0xc9, 0xc7,
|
||||
0xf5, 0x24, 0xa6, 0xaf, 0xc4, 0x74, 0x0a, 0xe5, 0x9f, 0x08, 0xcd, 0x7b, 0x69, 0x8c, 0x3d, 0x48,
|
||||
0x84, 0x02, 0x5e, 0xd5, 0x10, 0x90, 0xbd, 0xa6, 0xd7, 0x12, 0xef, 0x42, 0xe4, 0xb2, 0x79, 0x74,
|
||||
0xc2, 0x2f, 0xfd, 0xe0, 0x17, 0x7e, 0xc4, 0xe0, 0x79, 0x39, 0xe5, 0xee, 0x54, 0xf1, 0xd6, 0x0f,
|
||||
0x9e, 0xf8, 0xc1, 0x2f, 0xfc, 0xe0, 0xbd, 0x4d, 0x1f, 0xe9, 0x80, 0x45, 0xa7, 0x13, 0xdb, 0xa6,
|
||||
0x83, 0xda, 0x05, 0xf0, 0x18, 0xc5, 0x6d, 0x14, 0xe7, 0xa7, 0xfc, 0x26, 0xbd, 0xd1, 0x5b, 0xa2,
|
||||
0x80, 0xe0, 0xac, 0x09, 0x70, 0xf4, 0x7e, 0x9d, 0xb2, 0x04, 0x3f, 0x06, 0xdf, 0xe8, 0x12, 0xd8,
|
||||
0x07, 0x42, 0xd7, 0xdb, 0x36, 0xec, 0x16, 0x4f, 0x3f, 0xc8, 0x9f, 0x47, 0x91, 0xad, 0x44, 0x65,
|
||||
0xbe, 0xfb, 0xe6, 0xdb, 0x8f, 0x77, 0x6b, 0xdb, 0x6c, 0x2b, 0x7e, 0xb5, 0x66, 0x24, 0x3a, 0xaa,
|
||||
0x3f, 0x13, 0x3a, 0x58, 0x4e, 0x80, 0x89, 0xbf, 0xf3, 0xec, 0xcc, 0x6a, 0x45, 0x7c, 0x0f, 0x23,
|
||||
0xdf, 0xfd, 0xbc, 0x97, 0xef, 0xbd, 0xee, 0xcc, 0x3e, 0x12, 0x3a, 0x78, 0x00, 0x15, 0x20, 0xfc,
|
||||
0x27, 0x2e, 0x1f, 0xf6, 0xb2, 0xbe, 0x3f, 0xfe, 0xb2, 0x18, 0x92, 0xaf, 0x8b, 0x21, 0xf9, 0xbe,
|
||||
0x18, 0x92, 0x67, 0x77, 0xff, 0x61, 0xb9, 0xcb, 0x4a, 0x83, 0xc1, 0xb4, 0xca, 0x64, 0x10, 0xf7,
|
||||
0xf9, 0xce, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0xb9, 0x98, 0x4b, 0x83, 0x04, 0x00, 0x00,
|
||||
}
|
||||
228
pkg/apiclient/certificate/certificate.pb.gw.go
Normal file
228
pkg/apiclient/certificate/certificate.pb.gw.go
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: server/certificate/certificate.proto
|
||||
|
||||
/*
|
||||
Package certificate is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package certificate
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
|
||||
var (
|
||||
filter_CertificateService_List_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_CertificateService_List_0(ctx context.Context, marshaler runtime.Marshaler, client CertificateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RepositoryCertificateQuery
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_CertificateService_List_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.List(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_CertificateService_Create_0 = &utilities.DoubleArray{Encoding: map[string]int{"certificates": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
|
||||
)
|
||||
|
||||
func request_CertificateService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client CertificateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RepositoryCertificateCreateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Certificates); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_CertificateService_Create_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_CertificateService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_CertificateService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client CertificateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RepositoryCertificateQuery
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_CertificateService_Delete_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterCertificateServiceHandlerFromEndpoint is same as RegisterCertificateServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterCertificateServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterCertificateServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterCertificateServiceHandler registers the http handlers for service CertificateService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterCertificateServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterCertificateServiceHandlerClient(ctx, mux, NewCertificateServiceClient(conn))
|
||||
}
|
||||
|
||||
// RegisterCertificateServiceHandler registers the http handlers for service CertificateService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over the given implementation of "CertificateServiceClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "CertificateServiceClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "CertificateServiceClient" to call the correct interceptors.
|
||||
func RegisterCertificateServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client CertificateServiceClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_CertificateService_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CertificateService_List_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CertificateService_List_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_CertificateService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CertificateService_Create_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CertificateService_Create_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_CertificateService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CertificateService_Delete_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CertificateService_Delete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_CertificateService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "certificates"}, ""))
|
||||
|
||||
pattern_CertificateService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "certificates"}, ""))
|
||||
|
||||
pattern_CertificateService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "certificates"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_CertificateService_List_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CertificateService_Create_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CertificateService_Delete_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
|
@ -47,7 +47,7 @@ func (m *RepoAppsQuery) Reset() { *m = RepoAppsQuery{} }
|
|||
func (m *RepoAppsQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoAppsQuery) ProtoMessage() {}
|
||||
func (*RepoAppsQuery) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{0}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{0}
|
||||
}
|
||||
func (m *RepoAppsQuery) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -103,7 +103,7 @@ func (m *AppInfo) Reset() { *m = AppInfo{} }
|
|||
func (m *AppInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*AppInfo) ProtoMessage() {}
|
||||
func (*AppInfo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{1}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{1}
|
||||
}
|
||||
func (m *AppInfo) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -162,7 +162,7 @@ func (m *RepoAppDetailsQuery) Reset() { *m = RepoAppDetailsQuery{} }
|
|||
func (m *RepoAppDetailsQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoAppDetailsQuery) ProtoMessage() {}
|
||||
func (*RepoAppDetailsQuery) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{2}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{2}
|
||||
}
|
||||
func (m *RepoAppDetailsQuery) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -238,7 +238,7 @@ func (m *RepoAppsResponse) Reset() { *m = RepoAppsResponse{} }
|
|||
func (m *RepoAppsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoAppsResponse) ProtoMessage() {}
|
||||
func (*RepoAppsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{3}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{3}
|
||||
}
|
||||
func (m *RepoAppsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -286,7 +286,7 @@ func (m *RepoQuery) Reset() { *m = RepoQuery{} }
|
|||
func (m *RepoQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoQuery) ProtoMessage() {}
|
||||
func (*RepoQuery) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{4}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{4}
|
||||
}
|
||||
func (m *RepoQuery) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -322,6 +322,91 @@ func (m *RepoQuery) GetRepo() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// RepoAccessQuery is a query for checking access to a repo
|
||||
type RepoAccessQuery struct {
|
||||
// The URL to the repo
|
||||
Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
|
||||
// Username for accessing repo
|
||||
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
|
||||
// Password for accessing repo
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
// Private key data for accessing SSH repository
|
||||
SshPrivateKey string `protobuf:"bytes,4,opt,name=sshPrivateKey,proto3" json:"sshPrivateKey,omitempty"`
|
||||
// Whether to skip certificate or host key validation
|
||||
Insecure bool `protobuf:"varint,5,opt,name=insecure,proto3" json:"insecure,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) Reset() { *m = RepoAccessQuery{} }
|
||||
func (m *RepoAccessQuery) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoAccessQuery) ProtoMessage() {}
|
||||
func (*RepoAccessQuery) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{5}
|
||||
}
|
||||
func (m *RepoAccessQuery) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *RepoAccessQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_RepoAccessQuery.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *RepoAccessQuery) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RepoAccessQuery.Merge(dst, src)
|
||||
}
|
||||
func (m *RepoAccessQuery) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *RepoAccessQuery) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RepoAccessQuery.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RepoAccessQuery proto.InternalMessageInfo
|
||||
|
||||
func (m *RepoAccessQuery) GetRepo() string {
|
||||
if m != nil {
|
||||
return m.Repo
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetUsername() string {
|
||||
if m != nil {
|
||||
return m.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetPassword() string {
|
||||
if m != nil {
|
||||
return m.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetSshPrivateKey() string {
|
||||
if m != nil {
|
||||
return m.SshPrivateKey
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetInsecure() bool {
|
||||
if m != nil {
|
||||
return m.Insecure
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RepoResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
|
|
@ -332,7 +417,7 @@ func (m *RepoResponse) Reset() { *m = RepoResponse{} }
|
|||
func (m *RepoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoResponse) ProtoMessage() {}
|
||||
func (*RepoResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{5}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{6}
|
||||
}
|
||||
func (m *RepoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -373,7 +458,7 @@ func (m *RepoCreateRequest) Reset() { *m = RepoCreateRequest{} }
|
|||
func (m *RepoCreateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoCreateRequest) ProtoMessage() {}
|
||||
func (*RepoCreateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{6}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{7}
|
||||
}
|
||||
func (m *RepoCreateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -427,7 +512,7 @@ func (m *RepoUpdateRequest) Reset() { *m = RepoUpdateRequest{} }
|
|||
func (m *RepoUpdateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RepoUpdateRequest) ProtoMessage() {}
|
||||
func (*RepoUpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_repository_085a58cd976bcc45, []int{7}
|
||||
return fileDescriptor_repository_fd679778f6b4cef4, []int{8}
|
||||
}
|
||||
func (m *RepoUpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -469,6 +554,7 @@ func init() {
|
|||
proto.RegisterType((*RepoAppDetailsQuery)(nil), "repository.RepoAppDetailsQuery")
|
||||
proto.RegisterType((*RepoAppsResponse)(nil), "repository.RepoAppsResponse")
|
||||
proto.RegisterType((*RepoQuery)(nil), "repository.RepoQuery")
|
||||
proto.RegisterType((*RepoAccessQuery)(nil), "repository.RepoAccessQuery")
|
||||
proto.RegisterType((*RepoResponse)(nil), "repository.RepoResponse")
|
||||
proto.RegisterType((*RepoCreateRequest)(nil), "repository.RepoCreateRequest")
|
||||
proto.RegisterType((*RepoUpdateRequest)(nil), "repository.RepoUpdateRequest")
|
||||
|
|
@ -497,6 +583,8 @@ type RepositoryServiceClient interface {
|
|||
Update(ctx context.Context, in *RepoUpdateRequest, opts ...grpc.CallOption) (*v1alpha1.Repository, error)
|
||||
// Delete deletes a repo
|
||||
Delete(ctx context.Context, in *RepoQuery, opts ...grpc.CallOption) (*RepoResponse, error)
|
||||
// ValidateAccess validates access to a repository with given parameters
|
||||
ValidateAccess(ctx context.Context, in *RepoAccessQuery, opts ...grpc.CallOption) (*RepoResponse, error)
|
||||
}
|
||||
|
||||
type repositoryServiceClient struct {
|
||||
|
|
@ -561,6 +649,15 @@ func (c *repositoryServiceClient) Delete(ctx context.Context, in *RepoQuery, opt
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *repositoryServiceClient) ValidateAccess(ctx context.Context, in *RepoAccessQuery, opts ...grpc.CallOption) (*RepoResponse, error) {
|
||||
out := new(RepoResponse)
|
||||
err := c.cc.Invoke(ctx, "/repository.RepositoryService/ValidateAccess", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for RepositoryService service
|
||||
|
||||
type RepositoryServiceServer interface {
|
||||
|
|
@ -576,6 +673,8 @@ type RepositoryServiceServer interface {
|
|||
Update(context.Context, *RepoUpdateRequest) (*v1alpha1.Repository, error)
|
||||
// Delete deletes a repo
|
||||
Delete(context.Context, *RepoQuery) (*RepoResponse, error)
|
||||
// ValidateAccess validates access to a repository with given parameters
|
||||
ValidateAccess(context.Context, *RepoAccessQuery) (*RepoResponse, error)
|
||||
}
|
||||
|
||||
func RegisterRepositoryServiceServer(s *grpc.Server, srv RepositoryServiceServer) {
|
||||
|
|
@ -690,6 +789,24 @@ func _RepositoryService_Delete_Handler(srv interface{}, ctx context.Context, dec
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RepositoryService_ValidateAccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RepoAccessQuery)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RepositoryServiceServer).ValidateAccess(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/repository.RepositoryService/ValidateAccess",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RepositoryServiceServer).ValidateAccess(ctx, req.(*RepoAccessQuery))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _RepositoryService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "repository.RepositoryService",
|
||||
HandlerType: (*RepositoryServiceServer)(nil),
|
||||
|
|
@ -718,6 +835,10 @@ var _RepositoryService_serviceDesc = grpc.ServiceDesc{
|
|||
MethodName: "Delete",
|
||||
Handler: _RepositoryService_Delete_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ValidateAccess",
|
||||
Handler: _RepositoryService_ValidateAccess_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "server/repository/repository.proto",
|
||||
|
|
@ -908,6 +1029,61 @@ func (m *RepoQuery) MarshalTo(dAtA []byte) (int, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Repo) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.Repo)))
|
||||
i += copy(dAtA[i:], m.Repo)
|
||||
}
|
||||
if len(m.Username) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.Username)))
|
||||
i += copy(dAtA[i:], m.Username)
|
||||
}
|
||||
if len(m.Password) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.Password)))
|
||||
i += copy(dAtA[i:], m.Password)
|
||||
}
|
||||
if len(m.SshPrivateKey) > 0 {
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.SshPrivateKey)))
|
||||
i += copy(dAtA[i:], m.SshPrivateKey)
|
||||
}
|
||||
if m.Insecure {
|
||||
dAtA[i] = 0x28
|
||||
i++
|
||||
if m.Insecure {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *RepoResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
|
|
@ -1101,6 +1277,34 @@ func (m *RepoQuery) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Repo)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.Username)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.Password)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.SshPrivateKey)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.Insecure {
|
||||
n += 2
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *RepoResponse) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
|
|
@ -1736,6 +1940,193 @@ func (m *RepoQuery) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *RepoAccessQuery) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: RepoAccessQuery: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: RepoAccessQuery: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Repo", 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 > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Repo = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Username", 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 > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Username = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Password", 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 > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Password = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SshPrivateKey", 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 > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SshPrivateKey = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Insecure", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Insecure = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *RepoResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
@ -2081,52 +2472,58 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_085a58cd976bcc45)
|
||||
proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_fd679778f6b4cef4)
|
||||
}
|
||||
|
||||
var fileDescriptor_repository_085a58cd976bcc45 = []byte{
|
||||
// 679 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xc1, 0x6e, 0x13, 0x3d,
|
||||
0x10, 0xd6, 0xb6, 0x69, 0xda, 0xba, 0x7f, 0x7f, 0x81, 0x5b, 0xaa, 0xb0, 0xa4, 0x6d, 0x64, 0x0e,
|
||||
0xa4, 0x48, 0xac, 0x95, 0x94, 0x03, 0x42, 0x20, 0xd4, 0x52, 0x04, 0x15, 0x5c, 0x58, 0xc4, 0x01,
|
||||
0x0e, 0xa0, 0xed, 0x66, 0xd8, 0x98, 0x6c, 0xd6, 0xc6, 0x76, 0x22, 0x55, 0x55, 0x2f, 0x48, 0xf4,
|
||||
0x01, 0xe0, 0xce, 0x9d, 0x37, 0xe1, 0xc0, 0x01, 0x89, 0x17, 0x40, 0x15, 0x0f, 0x82, 0xec, 0xdd,
|
||||
0x6c, 0xb6, 0x69, 0xda, 0x22, 0x54, 0x71, 0x9b, 0x1d, 0xcf, 0x37, 0xdf, 0x67, 0xcf, 0xe7, 0x35,
|
||||
0x22, 0x0a, 0x64, 0x1f, 0x24, 0x95, 0x20, 0xb8, 0x62, 0x9a, 0xcb, 0xdd, 0x42, 0xe8, 0x09, 0xc9,
|
||||
0x35, 0xc7, 0x68, 0x98, 0x71, 0x17, 0x23, 0x1e, 0x71, 0x9b, 0xa6, 0x26, 0x4a, 0x2b, 0xdc, 0x6a,
|
||||
0xc4, 0x79, 0x14, 0x03, 0x0d, 0x04, 0xa3, 0x41, 0x92, 0x70, 0x1d, 0x68, 0xc6, 0x13, 0x95, 0xad,
|
||||
0x92, 0xce, 0x2d, 0xe5, 0x31, 0x6e, 0x57, 0x43, 0x2e, 0x81, 0xf6, 0x1b, 0x34, 0x82, 0x04, 0x64,
|
||||
0xa0, 0xa1, 0x95, 0xd5, 0x6c, 0x47, 0x4c, 0xb7, 0x7b, 0x3b, 0x5e, 0xc8, 0xbb, 0x34, 0x90, 0x96,
|
||||
0xe2, 0xad, 0x0d, 0x6e, 0x84, 0x2d, 0x2a, 0x3a, 0x91, 0x01, 0x2b, 0x1a, 0x08, 0x11, 0xb3, 0xd0,
|
||||
0x36, 0xa7, 0xfd, 0x46, 0x10, 0x8b, 0x76, 0x70, 0xbc, 0xd5, 0xe6, 0x69, 0xad, 0xec, 0x56, 0xce,
|
||||
0xdc, 0x32, 0xb9, 0x87, 0xe6, 0x7d, 0x10, 0x7c, 0x43, 0x08, 0xf5, 0xb4, 0x07, 0x72, 0x17, 0x63,
|
||||
0x54, 0x32, 0x45, 0x15, 0xa7, 0xe6, 0xd4, 0x67, 0x7d, 0x1b, 0x63, 0x17, 0xcd, 0x48, 0xe8, 0x33,
|
||||
0xc5, 0x78, 0x52, 0x99, 0xb0, 0xf9, 0xfc, 0x9b, 0x34, 0xd0, 0xf4, 0x86, 0x10, 0xdb, 0xc9, 0x1b,
|
||||
0x6e, 0xa0, 0x7a, 0x57, 0xc0, 0x00, 0x6a, 0x62, 0x93, 0x13, 0x81, 0x6e, 0x67, 0x30, 0x1b, 0x93,
|
||||
0x6f, 0x0e, 0x5a, 0xc8, 0x48, 0xb7, 0x40, 0x07, 0x2c, 0xfe, 0x3b, 0xea, 0xbc, 0xf7, 0xe4, 0xb0,
|
||||
0x37, 0x5e, 0x47, 0xa5, 0x36, 0xc4, 0xdd, 0x4a, 0xa9, 0xe6, 0xd4, 0xe7, 0x9a, 0xab, 0x5e, 0x61,
|
||||
0xc3, 0x8f, 0x20, 0xee, 0x8e, 0x50, 0xfa, 0xb6, 0x18, 0xdf, 0x41, 0xd3, 0x1d, 0xc5, 0x93, 0x04,
|
||||
0x74, 0x65, 0xca, 0xe2, 0x48, 0x11, 0xf7, 0x38, 0x5d, 0x1a, 0x85, 0x0e, 0x20, 0xe4, 0x2e, 0xba,
|
||||
0x30, 0x38, 0x42, 0x1f, 0x94, 0xe0, 0x89, 0x02, 0xbc, 0x86, 0xa6, 0x98, 0x86, 0xae, 0xaa, 0x38,
|
||||
0xb5, 0xc9, 0xfa, 0x5c, 0x73, 0xa1, 0xd8, 0x2f, 0x3b, 0x2e, 0x3f, 0xad, 0x20, 0xab, 0x68, 0xd6,
|
||||
0xc0, 0x4f, 0x3c, 0x02, 0xf2, 0x3f, 0xfa, 0xcf, 0x14, 0x0c, 0x7a, 0x93, 0x03, 0x07, 0x5d, 0x34,
|
||||
0x89, 0xfb, 0x12, 0x02, 0x0d, 0x3e, 0xbc, 0xeb, 0x81, 0xd2, 0xf8, 0x45, 0x01, 0x39, 0xd7, 0x7c,
|
||||
0xe0, 0x0d, 0xbd, 0xe1, 0x0d, 0xbc, 0x61, 0x83, 0xd7, 0x61, 0xcb, 0x13, 0x9d, 0xc8, 0x33, 0x36,
|
||||
0xf3, 0x0a, 0x36, 0xf3, 0x06, 0x36, 0xf3, 0xfc, 0x5c, 0x6a, 0x36, 0x83, 0x25, 0x54, 0xee, 0x09,
|
||||
0x05, 0x52, 0xdb, 0x09, 0xcc, 0xf8, 0xd9, 0x17, 0x49, 0x52, 0x1d, 0xcf, 0x45, 0xeb, 0x9f, 0xe8,
|
||||
0x68, 0x7e, 0x29, 0xa7, 0x84, 0x69, 0xf2, 0x19, 0xc8, 0x3e, 0x0b, 0x01, 0x1f, 0x38, 0xa8, 0xf4,
|
||||
0x84, 0x29, 0x8d, 0x2f, 0x15, 0x0f, 0x39, 0x3f, 0x52, 0x77, 0xfb, 0x5c, 0x24, 0x18, 0x06, 0x52,
|
||||
0x7d, 0xff, 0xe3, 0xd7, 0xa7, 0x89, 0x25, 0xbc, 0x68, 0x6f, 0x78, 0xbf, 0x31, 0xbc, 0x4e, 0x0c,
|
||||
0x14, 0xee, 0xa2, 0x19, 0x53, 0x65, 0x7c, 0x80, 0x2f, 0x8f, 0x6a, 0xc9, 0x2f, 0x98, 0x5b, 0x1d,
|
||||
0xb7, 0x94, 0x0f, 0xb7, 0x6e, 0x29, 0x08, 0xae, 0x8d, 0xa3, 0xa0, 0x7b, 0xe6, 0x6b, 0xdf, 0xfc,
|
||||
0x1d, 0x14, 0xfe, 0xe0, 0xa0, 0xf9, 0x87, 0x45, 0x5b, 0xe2, 0xd5, 0x31, 0x9d, 0x8b, 0x96, 0x75,
|
||||
0xc9, 0xc9, 0x05, 0xb9, 0x00, 0x6a, 0x05, 0xac, 0xe1, 0x6b, 0x67, 0x09, 0xa0, 0x7b, 0xe6, 0xc2,
|
||||
0xed, 0xe3, 0x8f, 0x0e, 0x2a, 0xa7, 0x56, 0xc4, 0xcb, 0xa3, 0xfd, 0x8f, 0x58, 0xd4, 0x3d, 0x1f,
|
||||
0x33, 0x10, 0x62, 0x15, 0x56, 0xc9, 0xd8, 0x29, 0xdc, 0x4e, 0x2d, 0xfb, 0xd9, 0x41, 0xe5, 0xd4,
|
||||
0x97, 0xc7, 0x45, 0x1d, 0xf1, 0xeb, 0x79, 0x89, 0xf2, 0xac, 0xa8, 0xba, 0x7b, 0xca, 0xdc, 0xac,
|
||||
0x8e, 0xfd, 0x4c, 0xe0, 0x2b, 0x54, 0xde, 0x82, 0x18, 0x34, 0x9c, 0x64, 0xdb, 0xca, 0x68, 0x3a,
|
||||
0x9f, 0xd0, 0x55, 0x4b, 0xb5, 0x7c, 0xfd, 0xca, 0x29, 0x13, 0xda, 0xdc, 0xfc, 0x7a, 0xb8, 0xe2,
|
||||
0x7c, 0x3f, 0x5c, 0x71, 0x7e, 0x1e, 0xae, 0x38, 0x2f, 0x6f, 0xfe, 0xc1, 0xa3, 0x13, 0xc6, 0x0c,
|
||||
0x12, 0x5d, 0x78, 0x21, 0x76, 0xca, 0xf6, 0x89, 0x58, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x24,
|
||||
0xdc, 0xe6, 0x9b, 0x3b, 0x07, 0x00, 0x00,
|
||||
var fileDescriptor_repository_fd679778f6b4cef4 = []byte{
|
||||
// 784 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4f, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0xd7, 0x26, 0x8e, 0xe3, 0x4c, 0x48, 0x80, 0x49, 0x88, 0xcc, 0xc6, 0x49, 0xac, 0x21, 0x12,
|
||||
0x0e, 0x82, 0x5d, 0xd9, 0xe1, 0x80, 0x10, 0x08, 0x25, 0x04, 0x41, 0x14, 0x0e, 0xb0, 0x08, 0x24,
|
||||
0x38, 0x80, 0x36, 0xeb, 0xc7, 0x7a, 0xf0, 0x7a, 0x67, 0x98, 0x19, 0x2f, 0xb2, 0xa2, 0x5c, 0x90,
|
||||
0x9a, 0x0f, 0xd0, 0xde, 0xdb, 0x5b, 0x3f, 0x4b, 0x0f, 0x3d, 0x54, 0xea, 0x17, 0xa8, 0xa2, 0x7e,
|
||||
0x90, 0x6a, 0x66, 0xff, 0x78, 0xe3, 0x38, 0x4e, 0x55, 0x45, 0xbd, 0xbd, 0x79, 0xf3, 0xde, 0xfb,
|
||||
0xfd, 0xde, 0x9f, 0x79, 0x83, 0x88, 0x04, 0x91, 0x80, 0x70, 0x05, 0x70, 0x26, 0xa9, 0x62, 0x62,
|
||||
0x54, 0x12, 0x1d, 0x2e, 0x98, 0x62, 0x18, 0x8d, 0x35, 0xf6, 0x7a, 0xc8, 0x42, 0x66, 0xd4, 0xae,
|
||||
0x96, 0x52, 0x0b, 0xbb, 0x11, 0x32, 0x16, 0x46, 0xe0, 0xfa, 0x9c, 0xba, 0x7e, 0x1c, 0x33, 0xe5,
|
||||
0x2b, 0xca, 0x62, 0x99, 0xdd, 0x92, 0xfe, 0x17, 0xd2, 0xa1, 0xcc, 0xdc, 0x06, 0x4c, 0x80, 0x9b,
|
||||
0xb4, 0xdd, 0x10, 0x62, 0x10, 0xbe, 0x82, 0x6e, 0x66, 0x73, 0x1c, 0x52, 0xd5, 0x1b, 0x9e, 0x3a,
|
||||
0x01, 0x1b, 0xb8, 0xbe, 0x30, 0x10, 0xff, 0x18, 0xe1, 0xb3, 0xa0, 0xeb, 0xf2, 0x7e, 0xa8, 0x9d,
|
||||
0xa5, 0xeb, 0x73, 0x1e, 0xd1, 0xc0, 0x04, 0x77, 0x93, 0xb6, 0x1f, 0xf1, 0x9e, 0x7f, 0x3d, 0xd4,
|
||||
0xe1, 0xac, 0x50, 0x26, 0x95, 0x5b, 0x53, 0x26, 0xdf, 0xa0, 0x15, 0x0f, 0x38, 0x3b, 0xe0, 0x5c,
|
||||
0xfe, 0x3c, 0x04, 0x31, 0xc2, 0x18, 0x55, 0xb4, 0x51, 0xdd, 0x6a, 0x5a, 0xad, 0x25, 0xcf, 0xc8,
|
||||
0xd8, 0x46, 0x35, 0x01, 0x09, 0x95, 0x94, 0xc5, 0xf5, 0x39, 0xa3, 0x2f, 0xce, 0xa4, 0x8d, 0x16,
|
||||
0x0f, 0x38, 0x3f, 0x8e, 0xff, 0x66, 0xda, 0x55, 0x8d, 0x38, 0xe4, 0xae, 0x5a, 0xd6, 0x3a, 0xee,
|
||||
0xab, 0x5e, 0xe6, 0x66, 0x64, 0xf2, 0xd4, 0x42, 0x6b, 0x19, 0xe8, 0x11, 0x28, 0x9f, 0x46, 0x6f,
|
||||
0x06, 0x5d, 0xc4, 0x9e, 0x1f, 0xc7, 0xc6, 0xfb, 0xa8, 0xd2, 0x83, 0x68, 0x50, 0xaf, 0x34, 0xad,
|
||||
0xd6, 0x72, 0x67, 0xc7, 0x29, 0x25, 0xfc, 0x03, 0x44, 0x83, 0x09, 0x48, 0xcf, 0x18, 0xe3, 0xaf,
|
||||
0xd0, 0x62, 0x5f, 0xb2, 0x38, 0x06, 0x55, 0x5f, 0x30, 0x7e, 0xa4, 0xec, 0x77, 0x92, 0x5e, 0x4d,
|
||||
0xba, 0xe6, 0x2e, 0xe4, 0x6b, 0xf4, 0x5e, 0x5e, 0x42, 0x0f, 0x24, 0x67, 0xb1, 0x04, 0xbc, 0x87,
|
||||
0x16, 0xa8, 0x82, 0x81, 0xac, 0x5b, 0xcd, 0xf9, 0xd6, 0x72, 0x67, 0xad, 0x1c, 0x2f, 0x2b, 0x97,
|
||||
0x97, 0x5a, 0x90, 0x1d, 0xb4, 0xa4, 0xdd, 0x6f, 0x2c, 0x01, 0x79, 0x64, 0xa1, 0x77, 0x0d, 0x40,
|
||||
0x10, 0x80, 0x9c, 0x5d, 0xaa, 0xa1, 0x04, 0x11, 0xfb, 0x03, 0xc8, 0x4b, 0x95, 0x9f, 0xf5, 0x1d,
|
||||
0xf7, 0xa5, 0xfc, 0x8f, 0x89, 0x6e, 0x56, 0xae, 0xe2, 0x8c, 0x77, 0xd1, 0x8a, 0x94, 0xbd, 0x9f,
|
||||
0x04, 0x4d, 0x7c, 0x05, 0x27, 0x30, 0x32, 0xb5, 0x5b, 0xf2, 0xae, 0x2a, 0x75, 0x04, 0x1a, 0x4b,
|
||||
0x08, 0x86, 0x02, 0x4c, 0x91, 0x6a, 0x5e, 0x71, 0x26, 0xab, 0xe8, 0x1d, 0x4d, 0x30, 0xcf, 0x9e,
|
||||
0x5c, 0x58, 0xe8, 0x7d, 0xad, 0xf8, 0x56, 0x80, 0xaf, 0xc0, 0x83, 0x7f, 0x87, 0x20, 0x15, 0xfe,
|
||||
0xbd, 0xc4, 0x79, 0xb9, 0xf3, 0x9d, 0x33, 0x9e, 0x5e, 0x27, 0x9f, 0x5e, 0x23, 0xfc, 0x15, 0x74,
|
||||
0x1d, 0xde, 0x0f, 0x1d, 0xfd, 0x10, 0x9c, 0xd2, 0x43, 0x70, 0xf2, 0x87, 0xe0, 0x78, 0x45, 0x31,
|
||||
0xb3, 0xd4, 0x37, 0x50, 0x75, 0xc8, 0x25, 0x08, 0x65, 0x12, 0xaf, 0x79, 0xd9, 0x89, 0xc4, 0x29,
|
||||
0x8f, 0x5f, 0x79, 0xf7, 0xad, 0xf0, 0xe8, 0x3c, 0x5e, 0x4c, 0x01, 0x53, 0xe5, 0x2f, 0x20, 0x12,
|
||||
0x1a, 0x00, 0xbe, 0xb0, 0x50, 0xe5, 0x47, 0x2a, 0x15, 0xfe, 0xa0, 0x3c, 0x06, 0x45, 0xd3, 0xed,
|
||||
0xe3, 0x3b, 0xa1, 0xa0, 0x11, 0x48, 0xe3, 0xff, 0xe7, 0x2f, 0x1f, 0xcc, 0x6d, 0xe0, 0x75, 0xb3,
|
||||
0x83, 0x92, 0xf6, 0xf8, 0xc1, 0x53, 0x90, 0x78, 0x80, 0x6a, 0xda, 0x4a, 0x4f, 0x2a, 0xfe, 0x70,
|
||||
0x92, 0x4b, 0xb1, 0x02, 0xec, 0xc6, 0xb4, 0xab, 0xa2, 0xb9, 0x2d, 0x03, 0x41, 0x70, 0x73, 0x1a,
|
||||
0x84, 0x7b, 0xa6, 0x4f, 0xe7, 0x7a, 0x7f, 0x49, 0x7c, 0xcf, 0x42, 0x2b, 0xdf, 0x97, 0x1f, 0x0e,
|
||||
0xde, 0x99, 0x12, 0xb9, 0xfc, 0xa8, 0x6c, 0x72, 0xb3, 0x41, 0x41, 0xc0, 0x35, 0x04, 0xf6, 0xf0,
|
||||
0xc7, 0xb7, 0x11, 0x70, 0xcf, 0xf4, 0x4a, 0x38, 0xc7, 0xf7, 0x2d, 0x54, 0x4d, 0x47, 0x11, 0x6f,
|
||||
0x4d, 0xc6, 0xbf, 0x32, 0xa2, 0xf6, 0xdd, 0x0c, 0x03, 0x21, 0x86, 0x61, 0x83, 0x4c, 0xed, 0xc2,
|
||||
0x97, 0xe9, 0xc8, 0x3e, 0xb4, 0x50, 0x35, 0x9d, 0xcb, 0xeb, 0xa4, 0xae, 0xcc, 0xeb, 0x5d, 0x91,
|
||||
0x72, 0x0c, 0xa9, 0x96, 0x3d, 0xa3, 0x6f, 0x86, 0xc7, 0x79, 0x46, 0xf0, 0x4f, 0x54, 0x3d, 0x82,
|
||||
0x08, 0x14, 0xdc, 0x34, 0xb6, 0xf5, 0x49, 0x75, 0xd1, 0xa1, 0x8f, 0x0c, 0xd4, 0xd6, 0x27, 0x9b,
|
||||
0x33, 0x3a, 0x84, 0xcf, 0xd0, 0xea, 0x6f, 0x7e, 0x44, 0x75, 0xa6, 0xe9, 0x66, 0xc3, 0x9b, 0xd7,
|
||||
0x9a, 0x3f, 0xde, 0x78, 0x33, 0xd0, 0x3a, 0x06, 0xed, 0x53, 0xb2, 0x3b, 0x6b, 0x1e, 0x92, 0x0c,
|
||||
0x2a, 0x4d, 0xee, 0xf0, 0xf0, 0xc9, 0xe5, 0xb6, 0xf5, 0xec, 0x72, 0xdb, 0x7a, 0x71, 0xb9, 0x6d,
|
||||
0xfd, 0xf1, 0xf9, 0x6b, 0xfc, 0xc9, 0x41, 0x44, 0x21, 0x56, 0xa5, 0x0f, 0xf4, 0xb4, 0x6a, 0x7e,
|
||||
0xd0, 0xfd, 0x57, 0x01, 0x00, 0x00, 0xff, 0xff, 0x44, 0x05, 0xf6, 0xec, 0x5a, 0x08, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,6 +205,45 @@ func request_RepositoryService_Delete_0(ctx context.Context, marshaler runtime.M
|
|||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_RepositoryService_ValidateAccess_0 = &utilities.DoubleArray{Encoding: map[string]int{"repo": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
|
||||
)
|
||||
|
||||
func request_RepositoryService_ValidateAccess_0(ctx context.Context, marshaler runtime.Marshaler, client RepositoryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RepoAccessQuery
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Repo); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["repo"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "repo")
|
||||
}
|
||||
|
||||
protoReq.Repo, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "repo", err)
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_RepositoryService_ValidateAccess_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ValidateAccess(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterRepositoryServiceHandlerFromEndpoint is same as RegisterRepositoryServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterRepositoryServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
|
|
@ -417,6 +456,35 @@ func RegisterRepositoryServiceHandlerClient(ctx context.Context, mux *runtime.Se
|
|||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_RepositoryService_ValidateAccess_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_RepositoryService_ValidateAccess_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_RepositoryService_ValidateAccess_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -432,6 +500,8 @@ var (
|
|||
pattern_RepositoryService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "repo.repo"}, ""))
|
||||
|
||||
pattern_RepositoryService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "repo"}, ""))
|
||||
|
||||
pattern_RepositoryService_ValidateAccess_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "repositories", "repo", "validate"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -446,4 +516,6 @@ var (
|
|||
forward_RepositoryService_Update_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_RepositoryService_Delete_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_RepositoryService_ValidateAccess_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application
|
|||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ConnectionState,ModifiedAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,JWTToken,ExpiresAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,JWTToken,IssuedAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,RepositoryCertificate,CertData
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,RepositoryCertificate,CertFingerprint
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,RepositoryCertificate,CertSubType
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,RepositoryCertificate,CertType
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,RepositoryCertificate,ServerName
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceActionDefinition,ActionLua
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceActions,ActionDiscoveryLua
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceOverride,HealthLua
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -484,17 +484,51 @@ message ProjectRole {
|
|||
|
||||
// Repository is a Git repository holding application configurations
|
||||
message Repository {
|
||||
// URL of the repo
|
||||
optional string repo = 1;
|
||||
|
||||
// Username for authenticating at the repo server
|
||||
optional string username = 2;
|
||||
|
||||
// Password for authenticating at the repo server
|
||||
optional string password = 3;
|
||||
|
||||
// SSH private key data for authenticating at the repo server
|
||||
optional string sshPrivateKey = 4;
|
||||
|
||||
optional ConnectionState connectionState = 5;
|
||||
|
||||
// InsecureIgnoreHostKey should not be used anymore, Insecure is favoured
|
||||
optional bool insecureIgnoreHostKey = 6;
|
||||
|
||||
// Whether the repo is insecure
|
||||
optional bool insecure = 7;
|
||||
}
|
||||
|
||||
// A RepositoryCertificate is either SSH known hosts entry or TLS certificate
|
||||
message RepositoryCertificate {
|
||||
// Name of the server the certificate is intended for
|
||||
optional string servername = 1;
|
||||
|
||||
// Type of certificate - currently "https" or "ssh"
|
||||
optional string type = 2;
|
||||
|
||||
// The sub type of the cert, i.e. "ssh-rsa"
|
||||
optional string cipher = 3;
|
||||
|
||||
// Actual certificate data, protocol dependent
|
||||
optional bytes certdata = 4;
|
||||
|
||||
// Certificate fingerprint
|
||||
optional string certfingerprint = 5;
|
||||
}
|
||||
|
||||
// RepositoryCertificateList is a collection of RepositoryCertificates
|
||||
message RepositoryCertificateList {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
|
||||
|
||||
// List of certificates to be processed
|
||||
repeated RepositoryCertificate items = 2;
|
||||
}
|
||||
|
||||
// RepositoryList is a collection of Repositories.
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.OperationState": schema_pkg_apis_application_v1alpha1_OperationState(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.ProjectRole": schema_pkg_apis_application_v1alpha1_ProjectRole(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.Repository": schema_pkg_apis_application_v1alpha1_Repository(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.RepositoryCertificate": schema_pkg_apis_application_v1alpha1_RepositoryCertificate(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.RepositoryCertificateList": schema_pkg_apis_application_v1alpha1_RepositoryCertificateList(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.RepositoryList": schema_pkg_apis_application_v1alpha1_RepositoryList(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.ResourceAction": schema_pkg_apis_application_v1alpha1_ResourceAction(ref),
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.ResourceActionDefinition": schema_pkg_apis_application_v1alpha1_ResourceActionDefinition(ref),
|
||||
|
|
@ -1749,26 +1751,30 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
|
|||
Properties: map[string]spec.Schema{
|
||||
"repo": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Description: "URL of the repo",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"username": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Description: "Username for authenticating at the repo server",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"password": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Description: "Password for authenticating at the repo server",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"sshPrivateKey": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Description: "SSH private key data for authenticating at the repo server",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"connectionState": {
|
||||
|
|
@ -1778,8 +1784,16 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
|
|||
},
|
||||
"insecureIgnoreHostKey": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
Description: "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"insecure": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Whether the repo is insecure",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -1791,6 +1805,89 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
|
|||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_application_v1alpha1_RepositoryCertificate(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A RepositoryCertificate is either SSH known hosts entry or TLS certificate",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"servername": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Name of the server the certificate is intended for",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type of certificate - currently \"https\" or \"ssh\"",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"cipher": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The sub type of the cert, i.e. \"ssh-rsa\"",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"certdata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Actual certificate data, protocol dependent",
|
||||
Type: []string{"string"},
|
||||
Format: "byte",
|
||||
},
|
||||
},
|
||||
"certfingerprint": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Certificate fingerprint",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"servername", "type", "cipher", "certdata", "certfingerprint"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_application_v1alpha1_RepositoryCertificateList(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "RepositoryCertificateList is a collection of RepositoryCertificates",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
|
||||
},
|
||||
},
|
||||
"items": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "List of certificates to be processed",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: ref("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.RepositoryCertificate"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"items"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.RepositoryCertificate", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_application_v1alpha1_RepositoryList(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
|
|
|||
|
|
@ -881,12 +881,19 @@ type ResourceActionParam struct {
|
|||
|
||||
// Repository is a Git repository holding application configurations
|
||||
type Repository struct {
|
||||
Repo string `json:"repo" protobuf:"bytes,1,opt,name=repo"`
|
||||
Username string `json:"username,omitempty" protobuf:"bytes,2,opt,name=username"`
|
||||
Password string `json:"password,omitempty" protobuf:"bytes,3,opt,name=password"`
|
||||
SSHPrivateKey string `json:"sshPrivateKey,omitempty" protobuf:"bytes,4,opt,name=sshPrivateKey"`
|
||||
ConnectionState ConnectionState `json:"connectionState,omitempty" protobuf:"bytes,5,opt,name=connectionState"`
|
||||
InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty" protobuf:"bytes,6,opt,name=insecureIgnoreHostKey"`
|
||||
// URL of the repo
|
||||
Repo string `json:"repo" protobuf:"bytes,1,opt,name=repo"`
|
||||
// Username for authenticating at the repo server
|
||||
Username string `json:"username,omitempty" protobuf:"bytes,2,opt,name=username"`
|
||||
// Password for authenticating at the repo server
|
||||
Password string `json:"password,omitempty" protobuf:"bytes,3,opt,name=password"`
|
||||
// SSH private key data for authenticating at the repo server
|
||||
SSHPrivateKey string `json:"sshPrivateKey,omitempty" protobuf:"bytes,4,opt,name=sshPrivateKey"`
|
||||
ConnectionState ConnectionState `json:"connectionState,omitempty" protobuf:"bytes,5,opt,name=connectionState"`
|
||||
// InsecureIgnoreHostKey should not be used anymore, Insecure is favoured
|
||||
InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty" protobuf:"bytes,6,opt,name=insecureIgnoreHostKey"`
|
||||
// Whether the repo is insecure
|
||||
Insecure bool `json:"insecure,omitempty" protobuf:"bytes,7,opt,name=insecure"`
|
||||
}
|
||||
|
||||
func (m *Repository) HasCredentials() bool {
|
||||
|
|
@ -899,6 +906,7 @@ func (m *Repository) CopyCredentialsFrom(source *Repository) {
|
|||
m.Password = source.Password
|
||||
m.SSHPrivateKey = source.SSHPrivateKey
|
||||
m.InsecureIgnoreHostKey = source.InsecureIgnoreHostKey
|
||||
m.Insecure = source.Insecure
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -908,6 +916,27 @@ type RepositoryList struct {
|
|||
Items []Repository `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// A RepositoryCertificate is either SSH known hosts entry or TLS certificate
|
||||
type RepositoryCertificate struct {
|
||||
// Name of the server the certificate is intended for
|
||||
ServerName string `json:"servername" protobuf:"bytes,1,opt,name=servername"`
|
||||
// Type of certificate - currently "https" or "ssh"
|
||||
CertType string `json:"type" protobuf:"bytes,2,opt,name=type"`
|
||||
// The sub type of the cert, i.e. "ssh-rsa"
|
||||
CertSubType string `json:"cipher" protobuf:"bytes,3,opt,name=cipher"`
|
||||
// Actual certificate data, protocol dependent
|
||||
CertData []byte `json:"certdata" protobuf:"bytes,4,opt,name=certdata"`
|
||||
// Certificate fingerprint
|
||||
CertFingerprint string `json:"certfingerprint" protobuf:"bytes,5,opt,name=certfingerprint"`
|
||||
}
|
||||
|
||||
// RepositoryCertificateList is a collection of RepositoryCertificates
|
||||
type RepositoryCertificateList struct {
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
// List of certificates to be processed
|
||||
Items []RepositoryCertificate `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// AppProjectList is list of AppProject resources
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type AppProjectList struct {
|
||||
|
|
|
|||
|
|
@ -1033,6 +1033,51 @@ func (in *Repository) DeepCopy() *Repository {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RepositoryCertificate) DeepCopyInto(out *RepositoryCertificate) {
|
||||
*out = *in
|
||||
if in.CertData != nil {
|
||||
in, out := &in.CertData, &out.CertData
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryCertificate.
|
||||
func (in *RepositoryCertificate) DeepCopy() *RepositoryCertificate {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RepositoryCertificate)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RepositoryCertificateList) DeepCopyInto(out *RepositoryCertificateList) {
|
||||
*out = *in
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]RepositoryCertificate, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryCertificateList.
|
||||
func (in *RepositoryCertificateList) DeepCopy() *RepositoryCertificateList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RepositoryCertificateList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RepositoryList) DeepCopyInto(out *RepositoryList) {
|
||||
*out = *in
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ func (s *Service) newClientResolveRevision(repo *v1alpha1.Repository, revision s
|
|||
|
||||
func (s *Service) newClient(repo *v1alpha1.Repository) (git.Client, error) {
|
||||
appPath := tempRepoPath(git.NormalizeGitURL(repo.Repo))
|
||||
return s.gitFactory.NewClient(repo.Repo, appPath, repo.Username, repo.Password, repo.SSHPrivateKey, repo.InsecureIgnoreHostKey)
|
||||
return s.gitFactory.NewClient(repo.Repo, appPath, repo.Username, repo.Password, repo.SSHPrivateKey, (repo.InsecureIgnoreHostKey || repo.Insecure))
|
||||
}
|
||||
|
||||
func runCommand(command v1alpha1.Command, path string, env []string) (string, error) {
|
||||
|
|
@ -753,7 +753,7 @@ func newCreds(repo *v1alpha1.Repository) git.Creds {
|
|||
return git.NewHTTPSCreds(repo.Username, repo.Password)
|
||||
}
|
||||
if repo.SSHPrivateKey != "" {
|
||||
return git.NewSSHCreds(repo.SSHPrivateKey, repo.InsecureIgnoreHostKey)
|
||||
return git.NewSSHCreds(repo.SSHPrivateKey, (repo.InsecureIgnoreHostKey || repo.Insecure))
|
||||
}
|
||||
return git.NopCreds{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (f *fakeGitClientFactory) NewClient(repoURL, path, username, password, sshP
|
|||
|
||||
func TestGenerateYamlManifestInDir(t *testing.T) {
|
||||
// update this value if we add/remove manifests
|
||||
const countOfManifests = 23
|
||||
const countOfManifests = 25
|
||||
|
||||
q := ManifestRequest{
|
||||
ApplicationSource: &argoappv1.ApplicationSource{},
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ func newTestAccountServer(ctx context.Context) (*fake.Clientset, *Server, *sessi
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
}, &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
|
|
|||
|
|
@ -90,7 +90,13 @@ func fakeListDirResponse() *repository.FileList {
|
|||
// return an ApplicationServiceServer which returns fake data
|
||||
func newTestAppServer(objects ...runtime.Object) *Server {
|
||||
kubeclientset := fake.NewSimpleClientset(&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "argocd-cm"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
Name: "argocd-cm",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
}, &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-secret",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,13 @@ var (
|
|||
},
|
||||
}
|
||||
argoCDCm = corev1.ConfigMap{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "argocd-cm", Namespace: "default"},
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"statusbadge.enabled": "true",
|
||||
},
|
||||
|
|
|
|||
85
server/certificate/certificate.go
Normal file
85
server/certificate/certificate.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package certificate
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
certificatepkg "github.com/argoproj/argo-cd/pkg/apiclient/certificate"
|
||||
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/reposerver"
|
||||
"github.com/argoproj/argo-cd/server/rbacpolicy"
|
||||
"github.com/argoproj/argo-cd/util/cache"
|
||||
"github.com/argoproj/argo-cd/util/db"
|
||||
"github.com/argoproj/argo-cd/util/rbac"
|
||||
)
|
||||
|
||||
// Server provides a Certificate service
|
||||
type Server struct {
|
||||
db db.ArgoDB
|
||||
repoClientset reposerver.Clientset
|
||||
enf *rbac.Enforcer
|
||||
cache *cache.Cache
|
||||
}
|
||||
|
||||
// NewServer returns a new instance of the Certificate service
|
||||
func NewServer(
|
||||
repoClientset reposerver.Clientset,
|
||||
db db.ArgoDB,
|
||||
enf *rbac.Enforcer,
|
||||
cache *cache.Cache,
|
||||
) *Server {
|
||||
return &Server{
|
||||
db: db,
|
||||
repoClientset: repoClientset,
|
||||
enf: enf,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: RBAC policies are currently an all-or-nothing approach, so there is no
|
||||
// fine grained control for certificate manipulation. Either a user has access
|
||||
// to a given certificate operation (get/create/delete), or it doesn't.
|
||||
|
||||
// Returns a list of configured certificates that match the query
|
||||
func (s *Server) List(ctx context.Context, q *certificatepkg.RepositoryCertificateQuery) (*appsv1.RepositoryCertificateList, error) {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceCertificates, rbacpolicy.ActionGet, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certList, err := s.db.ListRepoCertificates(ctx, &db.CertificateListSelector{
|
||||
HostNamePattern: q.GetHostNamePattern(),
|
||||
CertType: q.GetCertType(),
|
||||
CertSubType: q.GetCertSubType(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return certList, nil
|
||||
}
|
||||
|
||||
// Batch creates certificates for verifying repositories
|
||||
func (s *Server) Create(ctx context.Context, q *certificatepkg.RepositoryCertificateCreateRequest) (*appsv1.RepositoryCertificateList, error) {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceCertificates, rbacpolicy.ActionCreate, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs, err := s.db.CreateRepoCertificate(ctx, q.Certificates, q.Upsert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
// Batch deletes a list of certificates that match the query
|
||||
func (s *Server) Delete(ctx context.Context, q *certificatepkg.RepositoryCertificateQuery) (*appsv1.RepositoryCertificateList, error) {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceCertificates, rbacpolicy.ActionDelete, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs, err := s.db.RemoveRepoCertificates(ctx, &db.CertificateListSelector{
|
||||
HostNamePattern: q.GetHostNamePattern(),
|
||||
CertType: q.GetCertType(),
|
||||
CertSubType: q.GetCertSubType(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
51
server/certificate/certificate.proto
Normal file
51
server/certificate/certificate.proto
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
syntax = "proto3";
|
||||
option go_package = "github.com/argoproj/argo-cd/pkg/apiclient/certificate";
|
||||
|
||||
// Certificate Service
|
||||
//
|
||||
// Certificate Service API performs CRUD actions against repository certificate
|
||||
// resources.
|
||||
package certificate;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto";
|
||||
|
||||
// Message to query the server for configured repository certificates
|
||||
message RepositoryCertificateQuery {
|
||||
// A file-glob pattern (not regular expression) the host name has to match
|
||||
string hostNamePattern = 1;
|
||||
// The type of the certificate to match (ssh or https)
|
||||
string certType = 2;
|
||||
// The sub type of the certificate to match (protocol dependent, usually only used for ssh certs)
|
||||
string certSubType = 3;
|
||||
}
|
||||
|
||||
// Request to create a set of certificates
|
||||
message RepositoryCertificateCreateRequest {
|
||||
// List of certificates to be created
|
||||
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.RepositoryCertificateList certificates = 1;
|
||||
// Whether to upsert already existing certificates
|
||||
bool upsert = 2;
|
||||
}
|
||||
|
||||
message RepositoryCertificateResponse {}
|
||||
|
||||
service CertificateService {
|
||||
// List all available certificates
|
||||
rpc List(RepositoryCertificateQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.RepositoryCertificateList) {
|
||||
option (google.api.http).get = "/api/v1/certificates";
|
||||
}
|
||||
|
||||
// Creates the requested certificates on the server
|
||||
rpc Create(RepositoryCertificateCreateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.RepositoryCertificateList) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/certificates"
|
||||
body: "certificates"
|
||||
};
|
||||
}
|
||||
|
||||
rpc Delete(RepositoryCertificateQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.RepositoryCertificateList) {
|
||||
option (google.api.http).delete = "/api/v1/certificates";
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,13 @@ const testNamespace = "default"
|
|||
|
||||
func TestProjectServer(t *testing.T) {
|
||||
kubeclientset := fake.NewSimpleClientset(&corev1.ConfigMap{
|
||||
ObjectMeta: v1.ObjectMeta{Namespace: testNamespace, Name: "argocd-cm"},
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
Name: "argocd-cm",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
}, &corev1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "argocd-secret",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ const (
|
|||
ResourceProjects = "projects"
|
||||
ResourceApplications = "applications"
|
||||
ResourceRepositories = "repositories"
|
||||
ResourceCertificates = "certificates"
|
||||
|
||||
ActionGet = "get"
|
||||
ActionCreate = "create"
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func (s *Server) getConnectionState(ctx context.Context, url string) appsv1.Conn
|
|||
}
|
||||
repo, err := s.db.GetRepository(ctx, url)
|
||||
if err == nil {
|
||||
err = git.TestRepo(repo.Repo, repo.Username, repo.Password, repo.SSHPrivateKey, repo.InsecureIgnoreHostKey)
|
||||
err = git.TestRepo(repo.Repo, repo.Username, repo.Password, repo.SSHPrivateKey, repo.Insecure)
|
||||
}
|
||||
if err != nil {
|
||||
connectionState.Status = appsv1.ConnectionStatusFailed
|
||||
|
|
@ -82,7 +82,11 @@ func (s *Server) List(ctx context.Context, q *repositorypkg.RepoQuery) (*appsv1.
|
|||
items := make([]appsv1.Repository, 0)
|
||||
for _, url := range urls {
|
||||
if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, url) {
|
||||
items = append(items, appsv1.Repository{Repo: url})
|
||||
repo, err := s.db.GetRepository(ctx, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, appsv1.Repository{Repo: url, Insecure: (repo.InsecureIgnoreHostKey || repo.Insecure), Username: repo.Username})
|
||||
}
|
||||
}
|
||||
err = util.RunAllAsync(len(items), func(i int) error {
|
||||
|
|
@ -224,7 +228,7 @@ func (s *Server) Create(ctx context.Context, q *repositorypkg.RepoCreateRequest)
|
|||
return nil, err
|
||||
}
|
||||
r := q.Repo
|
||||
err := git.TestRepo(r.Repo, r.Username, r.Password, r.SSHPrivateKey, r.InsecureIgnoreHostKey)
|
||||
err := git.TestRepo(r.Repo, r.Username, r.Password, r.SSHPrivateKey, (r.InsecureIgnoreHostKey || r.Insecure))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -274,3 +278,18 @@ func (s *Server) Delete(ctx context.Context, q *repositorypkg.RepoQuery) (*repos
|
|||
err := s.db.DeleteRepository(ctx, q.Repo)
|
||||
return &repositorypkg.RepoResponse{}, err
|
||||
}
|
||||
|
||||
// ValidateAccess checks whether access to a repository is possible with the
|
||||
// given URL and credentials.
|
||||
func (s *Server) ValidateAccess(ctx context.Context, q *repositorypkg.RepoAccessQuery) (*repositorypkg.RepoResponse, error) {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionCreate, q.Repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := git.TestRepo(q.Repo, q.Username, q.Password, q.SshPrivateKey, q.Insecure)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &repositorypkg.RepoResponse{}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,20 @@ message RepoQuery {
|
|||
string repo = 1;
|
||||
}
|
||||
|
||||
// RepoAccessQuery is a query for checking access to a repo
|
||||
message RepoAccessQuery {
|
||||
// The URL to the repo
|
||||
string repo = 1;
|
||||
// Username for accessing repo
|
||||
string username = 2;
|
||||
// Password for accessing repo
|
||||
string password = 3;
|
||||
// Private key data for accessing SSH repository
|
||||
string sshPrivateKey = 4;
|
||||
// Whether to skip certificate or host key validation
|
||||
bool insecure = 5;
|
||||
}
|
||||
|
||||
message RepoResponse {}
|
||||
|
||||
message RepoCreateRequest {
|
||||
|
|
@ -94,4 +108,12 @@ service RepositoryService {
|
|||
option (google.api.http).delete = "/api/v1/repositories/{repo}";
|
||||
}
|
||||
|
||||
// ValidateAccess validates access to a repository with given parameters
|
||||
rpc ValidateAccess(RepoAccessQuery) returns (RepoResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/api/v1/repositories/{repo}/validate"
|
||||
body: "repo"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import (
|
|||
"github.com/argoproj/argo-cd/pkg/apiclient"
|
||||
accountpkg "github.com/argoproj/argo-cd/pkg/apiclient/account"
|
||||
applicationpkg "github.com/argoproj/argo-cd/pkg/apiclient/application"
|
||||
certificatepkg "github.com/argoproj/argo-cd/pkg/apiclient/certificate"
|
||||
clusterpkg "github.com/argoproj/argo-cd/pkg/apiclient/cluster"
|
||||
projectpkg "github.com/argoproj/argo-cd/pkg/apiclient/project"
|
||||
repositorypkg "github.com/argoproj/argo-cd/pkg/apiclient/repository"
|
||||
|
|
@ -60,6 +61,7 @@ import (
|
|||
"github.com/argoproj/argo-cd/server/account"
|
||||
"github.com/argoproj/argo-cd/server/application"
|
||||
"github.com/argoproj/argo-cd/server/badge"
|
||||
"github.com/argoproj/argo-cd/server/certificate"
|
||||
"github.com/argoproj/argo-cd/server/cluster"
|
||||
"github.com/argoproj/argo-cd/server/project"
|
||||
"github.com/argoproj/argo-cd/server/rbacpolicy"
|
||||
|
|
@ -454,6 +456,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
|||
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr)
|
||||
settingsService := settings.NewServer(a.settingsMgr)
|
||||
accountService := account.NewServer(a.sessionMgr, a.settingsMgr)
|
||||
certificateService := certificate.NewServer(a.RepoClientset, db, a.enf, a.Cache)
|
||||
versionpkg.RegisterVersionServiceServer(grpcS, &version.Server{})
|
||||
clusterpkg.RegisterClusterServiceServer(grpcS, clusterService)
|
||||
applicationpkg.RegisterApplicationServiceServer(grpcS, applicationService)
|
||||
|
|
@ -462,6 +465,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
|||
settingspkg.RegisterSettingsServiceServer(grpcS, settingsService)
|
||||
projectpkg.RegisterProjectServiceServer(grpcS, projectService)
|
||||
accountpkg.RegisterAccountServiceServer(grpcS, accountService)
|
||||
certificatepkg.RegisterCertificateServiceServer(grpcS, certificateService)
|
||||
// Register reflection service on gRPC server.
|
||||
reflection.Register(grpcS)
|
||||
grpc_prometheus.Register(grpcS)
|
||||
|
|
@ -538,6 +542,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
|
|||
mustRegisterGWHandler(sessionpkg.RegisterSessionServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
|
||||
mustRegisterGWHandler(settingspkg.RegisterSettingsServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
|
||||
mustRegisterGWHandler(projectpkg.RegisterProjectServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
|
||||
mustRegisterGWHandler(certificatepkg.RegisterCertificateServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
|
||||
|
||||
// Swagger UI
|
||||
swagger.ServeSwaggerUI(mux, assets.SwaggerJSON, "/swagger-ui")
|
||||
|
|
|
|||
33
test/certificates/cert1.pem
Normal file
33
test/certificates/cert1.pem
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFvTCCA6WgAwIBAgIUGrTmW3qc39zqnE08e3qNDhUkeWswDQYJKoZIhvcNAQEL
|
||||
BQAwbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdv
|
||||
MRQwEgYDVQQKDAtDYXBvbmUsIEluYzEQMA4GA1UECwwHU3BlY09wczEYMBYGA1UE
|
||||
AwwPZm9vLmV4YW1wbGUuY29tMB4XDTE5MDcwODEzNTUwNVoXDTIwMDcwNzEzNTUw
|
||||
NVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdv
|
||||
MRQwEgYDVQQKDAtDYXBvbmUsIEluYzEQMA4GA1UECwwHU3BlY09wczEYMBYGA1UE
|
||||
AwwPZm9vLmV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
|
||||
AgEA3csSO13w7qQXKeSLNcpeuAe6wAjXYbRkRl6ariqzTEDcFTKmy2QiXJTKoEGn
|
||||
bvwxq0T91var7rxY88SGL/qi8Zmo0tVSR0XvKSKcghFIkQOTyDmVgMPZGCvixt4q
|
||||
gQ7hUVSk4KkFmtcqBVuvnzI1d/DKfZAGKdmGcfRpuAsnVhac3swP0w4Tl1BFrK9U
|
||||
vuIkz4KwXG77s5oB8rMUnyuLasLsGNpvpvXhkcQRhp6vpcCO2bS7kOTTelAPIucw
|
||||
P37qkOEdZdiWCLrr57dmhg6tmcVlmBMg6JtmfLxn2HQd9ZrCKlkWxMk5NYs6CAW5
|
||||
kgbDZUWQTAsnHeoJKbcgtPkIbxDRxNpPukFMtbA4VEWv1EkODXy9FyEKDOI/PV6K
|
||||
/80oLkgCIhCkP2mvwSFheU0RHTuZ0o0vVolP5TEOq5iufnDN4wrxqb12o//XLRc0
|
||||
RiLqGVVxhFdyKCjVxcLfII9AAp5Tse4PMh6bf6jDfB3OMvGkhMbJWhKXdR2NUTl0
|
||||
esKawMPRXIn5g3oBdNm8kyRsTTnvB567pU8uNSmA8j3jxfGCPynI8JdiwKQuW/+P
|
||||
WgLIflgxqAfG85dVVOsFmF9o5o24dDslvv9yHnHH102c6ijPCg1EobqlyFzqqxOD
|
||||
Wf2OPjIkzoTH+O27VRugnY/maIU1nshNO7ViRX5zIxEUtNMCAwEAAaNTMFEwHQYD
|
||||
VR0OBBYEFNY4gDLgPBidogkmpO8nq5yAq5g+MB8GA1UdIwQYMBaAFNY4gDLgPBid
|
||||
ogkmpO8nq5yAq5g+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
|
||||
AJ0WGioNtGNg3m6ywpmxNThorQD5ZvDMlmZlDVk78E2wfNyMhwbVhKhlAnONv0wv
|
||||
kmsGjibY75nRZ+EK9PxSJ644841fryQXQ+bli5fhr7DW3uTKwaRsnzETJXRJuljq
|
||||
6+c6Zyg1/mqwnyx7YvPgVh3w496DYx/jm6Fm1IEq3BzOmn6H/gGPq3gbURzEqI3h
|
||||
P+kC2vJa8RZWrpa05Xk/Q1QUkErDX9vJghb9z3+GgirISZQzqWRghII/znv3NOE6
|
||||
zoIgaaWNFn8KPeBVpUoboH+IhpgibsnbTbI0G7AMtFq6qm3kn/4DZ2N2tuh1G2tT
|
||||
zR2Fh7hJbU7CrqxANrgnIoHG/nLSvzE24ckLb0Vj69uGQlwnZkn9fz6F7KytU+Az
|
||||
NoB2rjufaB0GQi1azdboMvdGSOxhSCAR8otWT5yDrywCqVnEvjw0oxKmuRduNe2/
|
||||
6AcG6TtK2/K+LHuhymiAwZM2qE6VD2odvb+tCzDkZOIeoIz/JcVlNpXE9FuVl250
|
||||
9NWvugeghq7tUv81iJ8ninBefJ4lUfxAehTPQqX+zXcfxgjvMRCi/ig73nLyhmjx
|
||||
r2AaraPFgrprnxUibP4L7jxdr+iiw5bWN9/B81PodrS7n5TNtnfnpZD6X6rThqOP
|
||||
xO7Tr5lAo74vNUkF2EHNaI28/RGnJPm2TIxZqy4rNH6L
|
||||
-----END CERTIFICATE-----
|
||||
34
test/certificates/cert2.pem
Normal file
34
test/certificates/cert2.pem
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
XWyb96wrUlv+E8I=
|
||||
-----END CERTIFICATE-----
|
||||
8
test/certificates/ssh_known_hosts
Normal file
8
test/certificates/ssh_known_hosts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# This file was automatically generated. DO NOT EDIT
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
|
|
@ -198,6 +198,9 @@ func NewFakeConfigMap() *apiv1.ConfigMap {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: FakeArgoCDNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: make(map[string]string),
|
||||
}
|
||||
|
|
|
|||
273
util/cert/cert.go
Normal file
273
util/cert/cert.go
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
// Utility functions for managing HTTPS server certificates and SSH known host
|
||||
// entries for ArgoCD
|
||||
package cert
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// A struct representing an entry in the list of SSH known hosts.
|
||||
type SSHKnownHostsEntry struct {
|
||||
// Hostname the key is for
|
||||
Host string
|
||||
// The type of the key
|
||||
SubType string
|
||||
// The data of the key, including the type
|
||||
Data string
|
||||
// The SHA256 fingerprint of the key
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
// A representation of a TLS certificate
|
||||
type TLSCertificate struct {
|
||||
// Subject of the certificate
|
||||
Subject string
|
||||
// Issuer of the certificate
|
||||
Issuer string
|
||||
// Certificate data
|
||||
Data string
|
||||
}
|
||||
|
||||
// Helper struct for certificate selection
|
||||
type CertificateListSelector struct {
|
||||
// Pattern to match the hostname with
|
||||
HostNamePattern string
|
||||
// Type of certificate to match
|
||||
CertType string
|
||||
// Subtype of certificate to match
|
||||
CertSubType string
|
||||
}
|
||||
|
||||
const (
|
||||
// Text marker indicating start of certificate in PEM format
|
||||
CertificateBeginMarker = "-----BEGIN CERTIFICATE-----"
|
||||
// Text marker indicating end of certificate in PEM format
|
||||
CertificateEndMarker = "-----END CERTIFICATE-----"
|
||||
// Maximum number of lines for a single certificate
|
||||
CertificateMaxLines = 128
|
||||
// Maximum number of certificates or known host entries in a stream
|
||||
CertificateMaxEntriesPerStream = 256
|
||||
// Local path where certificate data is stored
|
||||
CertificateDataPath = "/app/config/tls"
|
||||
)
|
||||
|
||||
// Decode a certificate in PEM format to X509 data structure
|
||||
func DecodePEMCertificateToX509(pemData string) (*x509.Certificate, error) {
|
||||
decodedData, _ := pem.Decode([]byte(pemData))
|
||||
if decodedData == nil {
|
||||
return nil, errors.New("Could not decode PEM data from input.")
|
||||
}
|
||||
x509Cert, err := x509.ParseCertificate(decodedData.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.New("Could not parse X509 data from input.")
|
||||
}
|
||||
return x509Cert, nil
|
||||
}
|
||||
|
||||
// Parse TLS certificates from a multiline string
|
||||
func ParseTLSCertificatesFromData(data string) ([]string, error) {
|
||||
return ParseTLSCertificatesFromStream(strings.NewReader(data))
|
||||
}
|
||||
|
||||
// Parse TLS certificates from a file
|
||||
func ParseTLSCertificatesFromPath(sourceFile string) ([]string, error) {
|
||||
fileHandle, err := os.Open(sourceFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fileHandle.Close()
|
||||
return ParseTLSCertificatesFromStream(fileHandle)
|
||||
}
|
||||
|
||||
// Parse TLS certificate data from a data stream. The stream may contain more
|
||||
// than one certificate. Each found certificate will generate a unique entry
|
||||
// in the returned slice, so the length of the slice indicates how many
|
||||
// certificates have been found.
|
||||
func ParseTLSCertificatesFromStream(stream io.Reader) ([]string, error) {
|
||||
scanner := bufio.NewScanner(stream)
|
||||
inCertData := false
|
||||
pemData := ""
|
||||
curLine := 0
|
||||
certLine := 0
|
||||
|
||||
certificateList := make([]string, 0)
|
||||
|
||||
// TODO: Implement maximum amount of data to parse
|
||||
// TODO: Implement error heuristics
|
||||
|
||||
for scanner.Scan() {
|
||||
curLine += 1
|
||||
if !inCertData {
|
||||
if strings.HasPrefix(scanner.Text(), CertificateBeginMarker) {
|
||||
certLine = 1
|
||||
inCertData = true
|
||||
pemData += scanner.Text() + "\n"
|
||||
}
|
||||
} else {
|
||||
certLine += 1
|
||||
pemData += scanner.Text() + "\n"
|
||||
if strings.HasPrefix(scanner.Text(), CertificateEndMarker) {
|
||||
inCertData = false
|
||||
certificateList = append(certificateList, pemData)
|
||||
pemData = ""
|
||||
}
|
||||
}
|
||||
|
||||
if certLine > CertificateMaxLines {
|
||||
return nil, errors.New("Maximum number of lines exceeded during certificate parsing.")
|
||||
}
|
||||
}
|
||||
|
||||
return certificateList, nil
|
||||
}
|
||||
|
||||
// Parse TLS certificates from a multiline string
|
||||
func ParseSSHKnownHostsFromData(data string) ([]string, error) {
|
||||
return ParseSSHKnownHostsFromStream(strings.NewReader(data))
|
||||
}
|
||||
|
||||
func ParseSSHKnownHostsFromPath(sourceFile string) ([]string, error) {
|
||||
fileHandle, err := os.Open(sourceFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fileHandle.Close()
|
||||
return ParseSSHKnownHostsFromStream(fileHandle)
|
||||
}
|
||||
|
||||
// Parses a list of strings in SSH's known host data format from a stream and
|
||||
// returns the valid entries in an array.
|
||||
func ParseSSHKnownHostsFromStream(stream io.Reader) ([]string, error) {
|
||||
scanner := bufio.NewScanner(stream)
|
||||
knownHostsLists := make([]string, 0)
|
||||
curLine := 0
|
||||
numEntries := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
curLine += 1
|
||||
lineData := scanner.Text()
|
||||
if IsValidSSHKnownHostsEntry(lineData) {
|
||||
numEntries += 1
|
||||
knownHostsLists = append(knownHostsLists, lineData)
|
||||
}
|
||||
}
|
||||
|
||||
return knownHostsLists, nil
|
||||
}
|
||||
|
||||
// Checks whether we can use a line from ssh_known_hosts data as an actual data
|
||||
// source for a RepoCertificate object. This function only checks for syntactic
|
||||
// validity, not if the data in the line is valid.
|
||||
func IsValidSSHKnownHostsEntry(line string) bool {
|
||||
trimmedEntry := strings.TrimSpace(line)
|
||||
// We ignore commented out lines - usually happens when copy and pasting
|
||||
// to the ConfigMap from a known_hosts file or from ssh-keyscan output.
|
||||
if len(trimmedEntry) == 0 || trimmedEntry[0] == '#' {
|
||||
return false
|
||||
}
|
||||
|
||||
// Each line should consist of three fields: host, type, data
|
||||
keyData := strings.SplitN(trimmedEntry, " ", 3)
|
||||
return len(keyData) == 3
|
||||
}
|
||||
|
||||
// Tokenize a known_hosts entry into hostname, key sub type and actual key data
|
||||
func TokenizeSSHKnownHostsEntry(knownHostsEntry string) (string, string, []byte, error) {
|
||||
knownHostsToken := strings.SplitN(knownHostsEntry, " ", 3)
|
||||
if len(knownHostsToken) != 3 {
|
||||
return "", "", nil, fmt.Errorf("Error while tokenizing input data.")
|
||||
}
|
||||
return knownHostsToken[0], knownHostsToken[1], []byte(knownHostsToken[2]), nil
|
||||
}
|
||||
|
||||
// Parse a raw known hosts line into a PublicKey object and a list of hosts the
|
||||
// key would be valid for.
|
||||
func KnownHostsLineToPublicKey(line string) ([]string, ssh.PublicKey, error) {
|
||||
_, hostnames, keyData, _, _, err := ssh.ParseKnownHosts([]byte(line))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return hostnames, keyData, nil
|
||||
}
|
||||
|
||||
func TokenizedDataToPublicKey(hostname string, subType string, rawKeyData string) ([]string, ssh.PublicKey, error) {
|
||||
hostnames, keyData, err := KnownHostsLineToPublicKey(fmt.Sprintf("%s %s %s", hostname, subType, rawKeyData))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return hostnames, keyData, nil
|
||||
}
|
||||
|
||||
// We do not use full fledged regular expression for matching the hostname.
|
||||
// Instead, we use a less expensive file system glob, which should be fully
|
||||
// sufficient for our use case.
|
||||
func MatchHostName(hostname, pattern string) bool {
|
||||
// If pattern is empty, we always return a match
|
||||
if pattern == "" {
|
||||
return true
|
||||
}
|
||||
match, err := filepath.Match(pattern, hostname)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
// base64 sha256 hash with the trailing equal sign removed
|
||||
func SSHFingerprintSHA256(key ssh.PublicKey) string {
|
||||
hash := sha256.Sum256(key.Marshal())
|
||||
b64hash := base64.StdEncoding.EncodeToString(hash[:])
|
||||
return strings.TrimRight(b64hash, "=")
|
||||
}
|
||||
|
||||
// Load certificate data from a file. If the file does not exist, we do not
|
||||
// consider it an error and just return empty data.
|
||||
func GetCertificateForConnect(serverName string) ([]string, error) {
|
||||
certPath := fmt.Sprintf("%s/%s", CertificateDataPath, serverName)
|
||||
certificates, err := ParseTLSCertificatesFromPath(certPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(certificates) == 0 {
|
||||
return nil, fmt.Errorf("No certificates found in existing file.")
|
||||
}
|
||||
|
||||
return certificates, nil
|
||||
}
|
||||
|
||||
func GetCertBundlePathForRepository(serverName string) (string, error) {
|
||||
certPath := fmt.Sprintf("%s/%s", CertificateDataPath, serverName)
|
||||
certs, err := GetCertificateForConnect(serverName)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
if len(certs) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return certPath, nil
|
||||
}
|
||||
|
||||
func GetCertPoolFromPEMData(pemData []string) *x509.CertPool {
|
||||
certPool := x509.NewCertPool()
|
||||
for _, pem := range pemData {
|
||||
certPool.AppendCertsFromPEM([]byte(pem))
|
||||
}
|
||||
return certPool
|
||||
}
|
||||
337
util/cert/cert_test.go
Normal file
337
util/cert/cert_test.go
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const Test_Cert1CN = "CN=foo.example.com,OU=SpecOps,O=Capone\\, Inc,L=Chicago,ST=IL,C=US"
|
||||
const Test_Cert2CN = "CN=bar.example.com,OU=Testsuite,O=Testing Corp,L=Hanover,ST=Lower Saxony,C=DE"
|
||||
const Test_TLSValidSingleCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const Test_TLSInvalidPEMData = `
|
||||
MIIF1zCCA7+gAwIBAgIUQdTcSHY2Sxd3Tq/v1eIEZPCNbOowDQYJKoZIhvcNAQEL
|
||||
BQAwezELMAkGA1UEBhMCREUxFTATBgNVBAgMDExvd2VyIFNheG9ueTEQMA4GA1UE
|
||||
BwwHSGFub3ZlcjEVMBMGA1UECgwMVGVzdGluZyBDb3JwMRIwEAYDVQQLDAlUZXN0
|
||||
c3VpdGUxGDAWBgNVBAMMD2Jhci5leGFtcGxlLmNvbTAeFw0xOTA3MDgxMzU2MTda
|
||||
Fw0yMDA3MDcxMzU2MTdaMHsxCzAJBgNVBAYTAkRFMRUwEwYDVQQIDAxMb3dlciBT
|
||||
YXhvbnkxEDAOBgNVBAcMB0hhbm92ZXIxFTATBgNVBAoMDFRlc3RpbmcgQ29ycDES
|
||||
MBAGA1UECwwJVGVzdHN1aXRlMRgwFgYDVQQDDA9iYXIuZXhhbXBsZS5jb20wggIi
|
||||
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCv4mHMdVUcafmaSHVpUM0zZWp5
|
||||
NFXfboxA4inuOkE8kZlbGSe7wiG9WqLirdr39Ts+WSAFA6oANvbzlu3JrEQ2CHPc
|
||||
CNQm6diPREFwcDPFCe/eMawbwkQAPVSHPts0UoRxnpZox5pn69ghncBR+jtvx+/u
|
||||
P6HdwW0qqTvfJnfAF1hBJ4oIk2AXiip5kkIznsAh9W6WRy6nTVCeetmIepDOGe0G
|
||||
ZJIRn/OfSz7NzKylfDCat2z3EAutyeT/5oXZoWOmGg/8T7pn/pR588GoYYKRQnp+
|
||||
YilqCPFX+az09EqqK/iHXnkdZ/Z2fCuU+9M/Zhrnlwlygl3RuVBI6xhm/ZsXtL2E
|
||||
Gxa61lNy6pyx5+hSxHEFEJshXLtioRd702VdLKxEOuYSXKeJDs1x9o6cJ75S6hko
|
||||
`
|
||||
|
||||
const Test_TLSInvalidSingleCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
XWyb96wrUlv+E8I=
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const Test_TLSValidMultiCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
XWyb96wrUlv+E8I=
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
// Taken from hack/ssh_known_hosts
|
||||
const Test_ValidSSHKnownHostsData = `
|
||||
# BitBucket
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
# GitHub
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
# GitLab
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
# Azure
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
`
|
||||
|
||||
const Test_InvalidSSHKnownHostsData = `
|
||||
bitbucket.org AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
# GitHub
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
# GitLab
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
# Azure
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
`
|
||||
|
||||
func Test_TLSCertificate_ValidPEM_ValidCert(t *testing.T) {
|
||||
// Valid PEM data, single certificate, expect array of length 1
|
||||
certificates, err := ParseTLSCertificatesFromData(Test_TLSValidSingleCert)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 1)
|
||||
// Expect good decode
|
||||
x509Cert, err := DecodePEMCertificateToX509(certificates[0])
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, x509Cert.Subject.String(), Test_Cert1CN)
|
||||
}
|
||||
|
||||
func Test_TLSCertificate_ValidPEM_InvalidCert(t *testing.T) {
|
||||
// Valid PEM data, but invalid certificate
|
||||
certificates, err := ParseTLSCertificatesFromData(Test_TLSInvalidSingleCert)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 1)
|
||||
// Expect bad decode
|
||||
_, err = DecodePEMCertificateToX509(certificates[0])
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func Test_TLSCertificate_InvalidPEM(t *testing.T) {
|
||||
// Invalid PEM data, expect array of length 0
|
||||
certificates, err := ParseTLSCertificatesFromData(Test_TLSInvalidPEMData)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 0)
|
||||
}
|
||||
|
||||
func Test_TLSCertificate_ValidPEM_ValidCert_Multi(t *testing.T) {
|
||||
// Valid PEM data, two certificates, expect array of length 2
|
||||
certificates, err := ParseTLSCertificatesFromData(Test_TLSValidMultiCert)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 2)
|
||||
// Expect good decode
|
||||
x509Cert, err := DecodePEMCertificateToX509(certificates[0])
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, x509Cert.Subject.String(), Test_Cert1CN)
|
||||
x509Cert, err = DecodePEMCertificateToX509(certificates[1])
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, x509Cert.Subject.String(), Test_Cert2CN)
|
||||
}
|
||||
|
||||
func Test_TLSCertificate_ValidPEM_ValidCert_FromFile(t *testing.T) {
|
||||
// Valid PEM data, single certificate from file, expect array of length 1
|
||||
certificates, err := ParseTLSCertificatesFromPath("../../test/certificates/cert1.pem")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 1)
|
||||
// Expect good decode
|
||||
x509Cert, err := DecodePEMCertificateToX509(certificates[0])
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, x509Cert.Subject.String(), Test_Cert1CN)
|
||||
}
|
||||
|
||||
func Test_TLSCertPool(t *testing.T) {
|
||||
certificates, err := ParseTLSCertificatesFromData(Test_TLSValidMultiCert)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(certificates), 2)
|
||||
certPool := GetCertPoolFromPEMData(certificates)
|
||||
assert.NotNil(t, certPool)
|
||||
}
|
||||
|
||||
func Test_TLSCertificate_CertFromNonExistingFile(t *testing.T) {
|
||||
// Non-existing file, expect err
|
||||
_, err := ParseTLSCertificatesFromPath("../../test/certificates/cert_nonexisting.pem")
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func Test_SSHKnownHostsData_ParseData(t *testing.T) {
|
||||
// Expect valid data with 7 known host entries
|
||||
entries, err := ParseSSHKnownHostsFromData(Test_ValidSSHKnownHostsData)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(entries), 7)
|
||||
}
|
||||
|
||||
func Test_SSHKnownHostsData_ParseFile(t *testing.T) {
|
||||
// Expect valid data with 7 known host entries
|
||||
entries, err := ParseSSHKnownHostsFromPath("../../test/certificates/ssh_known_hosts")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(entries), 7)
|
||||
}
|
||||
|
||||
func Test_SSHKnownHostsData_ParseNonExistingFile(t *testing.T) {
|
||||
// Expect valid data with 7 known host entries
|
||||
entries, err := ParseSSHKnownHostsFromPath("../../test/certificates/ssh_known_hosts_invalid")
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, entries)
|
||||
}
|
||||
|
||||
func Test_SSHKnownHostsData_Tokenize(t *testing.T) {
|
||||
// All entries should parse to valid SSH public keys
|
||||
// All entries should be tokenizable, and tokens should be feedable to decoder
|
||||
entries, err := ParseSSHKnownHostsFromData(Test_ValidSSHKnownHostsData)
|
||||
assert.Nil(t, err)
|
||||
for _, entry := range entries {
|
||||
hosts, _, err := KnownHostsLineToPublicKey(entry)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(hosts), 1)
|
||||
hoststring, subtype, certdata, err := TokenizeSSHKnownHostsEntry(entry)
|
||||
assert.Nil(t, err)
|
||||
hosts, _, err = TokenizedDataToPublicKey(hoststring, subtype, string(certdata))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(hosts), 1)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MatchHostName(t *testing.T) {
|
||||
matchHostName := "foo.example.com"
|
||||
assert.Equal(t, MatchHostName(matchHostName, "*"), true)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "*.example.com"), true)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "foo.*"), true)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "foo.*.com"), true)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "fo?.example.com"), true)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "foo?.example.com"), false)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "bar.example.com"), false)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "*.otherexample.com"), false)
|
||||
assert.Equal(t, MatchHostName(matchHostName, "foo.otherexample.*"), false)
|
||||
}
|
||||
|
||||
func Test_SSHFingerprintSHA256(t *testing.T) {
|
||||
// actual SHA256 fingerprints for keys defined above
|
||||
fingerprints := [...]string{
|
||||
"zzXQOXSRBEiUtuE8AikJYKwbHaxvSc0ojez9YXaGp1A",
|
||||
"nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8",
|
||||
"HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw",
|
||||
"eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8",
|
||||
"ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ",
|
||||
"ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og",
|
||||
"ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og",
|
||||
}
|
||||
entries, err := ParseSSHKnownHostsFromData(Test_ValidSSHKnownHostsData)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(entries), 7)
|
||||
for idx, entry := range entries {
|
||||
_, pubKey, err := KnownHostsLineToPublicKey(entry)
|
||||
assert.Nil(t, err)
|
||||
fp := SSHFingerprintSHA256(pubKey)
|
||||
assert.Equal(t, fp, fingerprints[idx])
|
||||
}
|
||||
}
|
||||
453
util/db/certificate.go
Normal file
453
util/db/certificate.go
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/argoproj/argo-cd/common"
|
||||
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
certutil "github.com/argoproj/argo-cd/util/cert"
|
||||
)
|
||||
|
||||
// A struct representing an entry in the list of SSH known hosts.
|
||||
type SSHKnownHostsEntry struct {
|
||||
// Hostname the key is for
|
||||
Host string
|
||||
// The type of the key
|
||||
SubType string
|
||||
// The data of the key, including the type
|
||||
Data string
|
||||
// The SHA256 fingerprint of the key
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
// A representation of a TLS certificate
|
||||
type TLSCertificate struct {
|
||||
// Subject of the certificate
|
||||
Subject string
|
||||
// Issuer of the certificate
|
||||
Issuer string
|
||||
// Certificate data
|
||||
Data string
|
||||
}
|
||||
|
||||
// Helper struct for certificate selection
|
||||
type CertificateListSelector struct {
|
||||
// Pattern to match the hostname with
|
||||
HostNamePattern string
|
||||
// Type of certificate to match
|
||||
CertType string
|
||||
// Subtype of certificate to match
|
||||
CertSubType string
|
||||
}
|
||||
|
||||
// Get a list of all configured repository certificates matching the given
|
||||
// selector.
|
||||
func (db *db) ListRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appsv1.RepositoryCertificateList, error) {
|
||||
|
||||
// selector may be given as nil, but we need at least an empty data structure
|
||||
// so we create it if necessary.
|
||||
if selector == nil {
|
||||
selector = &CertificateListSelector{}
|
||||
}
|
||||
|
||||
certificates := make([]appsv1.RepositoryCertificate, 0)
|
||||
|
||||
// Get all SSH known host entries
|
||||
if selector.CertType == "" || selector.CertType == "*" || selector.CertType == "ssh" {
|
||||
sshKnownHosts, err := db.getSSHKnownHostsData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range sshKnownHosts {
|
||||
if certutil.MatchHostName(entry.Host, selector.HostNamePattern) && (selector.CertSubType == "" || selector.CertSubType == "*" || selector.CertSubType == entry.SubType) {
|
||||
certificates = append(certificates, appsv1.RepositoryCertificate{
|
||||
ServerName: entry.Host,
|
||||
CertType: "ssh",
|
||||
CertSubType: entry.SubType,
|
||||
CertData: []byte(entry.Data),
|
||||
CertFingerprint: entry.Fingerprint,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get all TLS certificates
|
||||
if selector.CertType == "" || selector.CertType == "*" || selector.CertType == "https" || selector.CertType == "tls" {
|
||||
tlsCertificates, err := db.getTLSCertificateData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, entry := range tlsCertificates {
|
||||
if certutil.MatchHostName(entry.Subject, selector.HostNamePattern) {
|
||||
pemEntries, err := certutil.ParseTLSCertificatesFromData(entry.Data)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, pemEntry := range pemEntries {
|
||||
certificates = append(certificates, appsv1.RepositoryCertificate{
|
||||
ServerName: entry.Subject,
|
||||
CertType: "https",
|
||||
CertData: []byte(pemEntry),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &appsv1.RepositoryCertificateList{
|
||||
Items: certificates,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get a single certificate from the datastore
|
||||
func (db *db) GetRepoCertificate(ctx context.Context, serverType string, serverName string) (*appsv1.RepositoryCertificate, error) {
|
||||
if serverType == "ssh" {
|
||||
sshKnownHostsList, err := db.getSSHKnownHostsData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, entry := range sshKnownHostsList {
|
||||
if entry.Host == serverName {
|
||||
repo := &appsv1.RepositoryCertificate{
|
||||
ServerName: entry.Host,
|
||||
CertType: "ssh",
|
||||
CertSubType: entry.SubType,
|
||||
CertData: []byte(entry.Data),
|
||||
CertFingerprint: entry.Fingerprint,
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fail
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Create one or more repository certificates and returns a list of certificates
|
||||
// actually created.
|
||||
func (db *db) CreateRepoCertificate(ctx context.Context, certificates *appsv1.RepositoryCertificateList, upsert bool) (*appsv1.RepositoryCertificateList, error) {
|
||||
var (
|
||||
saveSSHData bool = false
|
||||
saveTLSData bool = false
|
||||
)
|
||||
|
||||
sshKnownHostsList, err := db.getSSHKnownHostsData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsCertificates, err := db.getTLSCertificateData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This will hold the final list of certificates that have been created
|
||||
created := make([]appsv1.RepositoryCertificate, 0)
|
||||
|
||||
// Each request can contain multiple certificates of different types, so we
|
||||
// make sure to handle each request accordingly.
|
||||
for _, certificate := range certificates.Items {
|
||||
if certificate.CertType == "ssh" {
|
||||
// Whether we have a new certificate entry
|
||||
newEntry := true
|
||||
// Whether we have upserted an existing certificate entry
|
||||
upserted := false
|
||||
|
||||
// Check whether known hosts entry already exists. Must match hostname
|
||||
// and the key sub type (e.g. ssh-rsa). It is considered an error if we
|
||||
// already have a corresponding key and upsert was not specified.
|
||||
for _, entry := range sshKnownHostsList {
|
||||
if entry.Host == certificate.ServerName && entry.SubType == certificate.CertSubType {
|
||||
if !upsert && entry.Data != string(certificate.CertData) {
|
||||
return nil, fmt.Errorf("Key for '%s' (subtype: '%s') already exist and upsert was not specified.", entry.Host, entry.SubType)
|
||||
} else {
|
||||
// Do not add an entry on upsert, but remember if we actual did an
|
||||
// upsert.
|
||||
newEntry = false
|
||||
if entry.Data != string(certificate.CertData) {
|
||||
entry.Data = string(certificate.CertData)
|
||||
upserted = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that we received a valid public host key by parsing it
|
||||
_, _, rawKeyData, _, _, err := ssh.ParseKnownHosts([]byte(fmt.Sprintf("%s %s %s", certificate.ServerName, certificate.CertSubType, certificate.CertData)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if newEntry {
|
||||
sshKnownHostsList = append(sshKnownHostsList, &SSHKnownHostsEntry{
|
||||
Host: certificate.ServerName,
|
||||
Data: string(certificate.CertData),
|
||||
SubType: certificate.CertSubType,
|
||||
})
|
||||
}
|
||||
|
||||
// If we created a new entry, or if we upserted an existing one, we need
|
||||
// to save the data and notify the consumer about the operation.
|
||||
if newEntry || upserted {
|
||||
certificate.CertFingerprint = certutil.SSHFingerprintSHA256(rawKeyData)
|
||||
created = append(created, certificate)
|
||||
saveSSHData = true
|
||||
}
|
||||
|
||||
} else if certificate.CertType == "https" {
|
||||
var tlsCertificate *TLSCertificate = nil
|
||||
newEntry := true
|
||||
upserted := false
|
||||
pemCreated := make([]string, 0)
|
||||
|
||||
for _, entry := range tlsCertificates {
|
||||
// We have an entry for this server already. Check for upsert.
|
||||
if entry.Subject == certificate.ServerName {
|
||||
newEntry = false
|
||||
if entry.Data != string(certificate.CertData) {
|
||||
if !upsert {
|
||||
return nil, fmt.Errorf("TLS certificate for server '%s' already exist and upsert was not specified.", entry.Subject)
|
||||
}
|
||||
}
|
||||
// Store pointer to this entry for later use.
|
||||
tlsCertificate = entry
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Check for validity of data received
|
||||
pemData, err := certutil.ParseTLSCertificatesFromData(string(certificate.CertData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We should have at least one valid PEM entry
|
||||
if len(pemData) == 0 {
|
||||
return nil, fmt.Errorf("No valid PEM data received.")
|
||||
}
|
||||
|
||||
// Make sure we have valid X509 certificates in the data
|
||||
for _, entry := range pemData {
|
||||
_, err := certutil.DecodePEMCertificateToX509(entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pemCreated = append(pemCreated, entry)
|
||||
}
|
||||
|
||||
// New certificate if pointer to existing cert is nil
|
||||
if tlsCertificate == nil {
|
||||
tlsCertificate = &TLSCertificate{
|
||||
Subject: certificate.ServerName,
|
||||
Data: string(certificate.CertData),
|
||||
}
|
||||
tlsCertificates = append(tlsCertificates, tlsCertificate)
|
||||
} else {
|
||||
// We have made sure the upsert flag was set above. Now just figure out
|
||||
// again if we have to actually update the data in the existing cert.
|
||||
if tlsCertificate.Data != string(certificate.CertData) {
|
||||
tlsCertificate.Data = string(certificate.CertData)
|
||||
upserted = true
|
||||
}
|
||||
}
|
||||
|
||||
if newEntry || upserted {
|
||||
// We append the certificate for every PEM entry in the request, so the
|
||||
// caller knows that we processed each single item.
|
||||
for _, entry := range pemCreated {
|
||||
created = append(created, appsv1.RepositoryCertificate{
|
||||
ServerName: certificate.ServerName,
|
||||
CertType: "https",
|
||||
CertData: []byte(entry),
|
||||
})
|
||||
}
|
||||
saveTLSData = true
|
||||
}
|
||||
} else {
|
||||
// Invalid/unknown certificate type
|
||||
return nil, fmt.Errorf("Unknown certificate type: %s", certificate.CertType)
|
||||
}
|
||||
}
|
||||
|
||||
if saveSSHData {
|
||||
err = db.settingsMgr.SaveSSHKnownHostsData(ctx, knownHostsDataToStrings(sshKnownHostsList))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if saveTLSData {
|
||||
err = db.settingsMgr.SaveTLSCertificateData(ctx, tlsCertificatesToMap(tlsCertificates))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &appsv1.RepositoryCertificateList{Items: created}, nil
|
||||
}
|
||||
|
||||
// Batch remove configured certificates according to the selector query
|
||||
func (db *db) RemoveRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appsv1.RepositoryCertificateList, error) {
|
||||
var (
|
||||
knownHostsOld []*SSHKnownHostsEntry
|
||||
knownHostsNew []*SSHKnownHostsEntry
|
||||
tlsCertificatesOld []*TLSCertificate
|
||||
tlsCertificatesNew []*TLSCertificate
|
||||
err error
|
||||
)
|
||||
|
||||
removed := &appsv1.RepositoryCertificateList{
|
||||
Items: make([]appsv1.RepositoryCertificate, 0),
|
||||
}
|
||||
|
||||
if selector.CertType == "" || selector.CertType == "ssh" || selector.CertType == "*" {
|
||||
knownHostsOld, err = db.getSSHKnownHostsData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
knownHostsNew = make([]*SSHKnownHostsEntry, 0)
|
||||
|
||||
for _, entry := range knownHostsOld {
|
||||
if matchSSHKnownHostsEntry(entry, selector) {
|
||||
removed.Items = append(removed.Items, appsv1.RepositoryCertificate{
|
||||
ServerName: entry.Host,
|
||||
CertType: "ssh",
|
||||
CertSubType: entry.SubType,
|
||||
CertData: []byte(entry.Data),
|
||||
})
|
||||
} else {
|
||||
knownHostsNew = append(knownHostsNew, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if selector.CertType == "" || selector.CertType == "*" || selector.CertType == "https" || selector.CertType == "tls" {
|
||||
tlsCertificatesOld, err = db.getTLSCertificateData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsCertificatesNew = make([]*TLSCertificate, 0)
|
||||
for _, entry := range tlsCertificatesOld {
|
||||
if certutil.MatchHostName(entry.Subject, selector.HostNamePattern) {
|
||||
// Wrap each PEM certificate into its own RepositoryCertificate object
|
||||
// so the caller knows what has been removed actually.
|
||||
//
|
||||
// The downside of this is, only valid data can be removed from the CM,
|
||||
// so if the data somehow got corrupted, it can only be removed by
|
||||
// means of editing the CM directly using e.g. kubectl.
|
||||
pemCertificates, err := certutil.ParseTLSCertificatesFromData(entry.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pemCertificates) > 0 {
|
||||
for _, pem := range pemCertificates {
|
||||
removed.Items = append(removed.Items, appsv1.RepositoryCertificate{
|
||||
ServerName: entry.Subject,
|
||||
CertType: "https",
|
||||
CertData: []byte(pem),
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tlsCertificatesNew = append(tlsCertificatesNew, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(knownHostsNew) < len(knownHostsOld) {
|
||||
err = db.settingsMgr.SaveSSHKnownHostsData(ctx, knownHostsDataToStrings(knownHostsNew))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(tlsCertificatesNew) < len(tlsCertificatesOld) {
|
||||
err = db.settingsMgr.SaveTLSCertificateData(ctx, tlsCertificatesToMap(tlsCertificatesNew))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return removed, nil
|
||||
}
|
||||
|
||||
// Converts list of known hosts data to array of strings, suitable for storing
|
||||
// in a known_hosts file for SSH.
|
||||
func knownHostsDataToStrings(knownHostsList []*SSHKnownHostsEntry) []string {
|
||||
knownHostsData := make([]string, 0)
|
||||
for _, entry := range knownHostsList {
|
||||
knownHostsData = append(knownHostsData, fmt.Sprintf("%s %s %s", entry.Host, entry.SubType, entry.Data))
|
||||
}
|
||||
return knownHostsData
|
||||
}
|
||||
|
||||
// Converts list of TLS certificates to a map whose key will be the certificate
|
||||
// subject and the data will be a string containing TLS certificate data as PEM
|
||||
func tlsCertificatesToMap(tlsCertificates []*TLSCertificate) map[string]string {
|
||||
certMap := make(map[string]string)
|
||||
for _, entry := range tlsCertificates {
|
||||
certMap[entry.Subject] = entry.Data
|
||||
}
|
||||
return certMap
|
||||
}
|
||||
|
||||
// Get the TLS certificate data from the config map
|
||||
func (db *db) getTLSCertificateData() ([]*TLSCertificate, error) {
|
||||
certificates := make([]*TLSCertificate, 0)
|
||||
certCM, err := db.settingsMgr.GetNamedConfigMap(common.ArgoCDTLSCertsConfigMapName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for key, entry := range certCM.Data {
|
||||
certificates = append(certificates, &TLSCertificate{Subject: key, Data: entry})
|
||||
}
|
||||
|
||||
return certificates, nil
|
||||
}
|
||||
|
||||
// Gets the SSH known host data from ConfigMap and parse it into an array of
|
||||
// SSHKnownHostEntry structs.
|
||||
func (db *db) getSSHKnownHostsData() ([]*SSHKnownHostsEntry, error) {
|
||||
certCM, err := db.settingsMgr.GetNamedConfigMap(common.ArgoCDKnownHostsConfigMapName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sshKnownHostsData := certCM.Data["ssh_known_hosts"]
|
||||
entries := make([]*SSHKnownHostsEntry, 0)
|
||||
|
||||
// ssh_known_hosts data contains one key per line, so we must iterate over
|
||||
// the whole data to get all keys.
|
||||
//
|
||||
// We validate the data found to a certain extent before we accept them as
|
||||
// entry into our list to be returned.
|
||||
//
|
||||
sshKnownHostsEntries, err := certutil.ParseSSHKnownHostsFromData(sshKnownHostsData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range sshKnownHostsEntries {
|
||||
hostname, subType, keyData, err := certutil.TokenizeSSHKnownHostsEntry(entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries = append(entries, &SSHKnownHostsEntry{
|
||||
Host: hostname,
|
||||
SubType: subType,
|
||||
Data: string(keyData),
|
||||
})
|
||||
}
|
||||
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func matchSSHKnownHostsEntry(entry *SSHKnownHostsEntry, selector *CertificateListSelector) bool {
|
||||
return certutil.MatchHostName(entry.Host, selector.HostNamePattern) && (selector.CertSubType == "" || selector.CertSubType == "*" || selector.CertSubType == entry.SubType)
|
||||
}
|
||||
736
util/db/certificate_test.go
Normal file
736
util/db/certificate_test.go
Normal file
|
|
@ -0,0 +1,736 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/util/settings"
|
||||
)
|
||||
|
||||
const Test_Cert1CN = "CN=foo.example.com,OU=SpecOps,O=Capone\\, Inc,L=Chicago,ST=IL,C=US"
|
||||
const Test_Cert2CN = "CN=bar.example.com,OU=Testsuite,O=Testing Corp,L=Hanover,ST=Lower Saxony,C=DE"
|
||||
|
||||
var Test_TLS_Subjects []string = []string{
|
||||
"CN=foo.example.com,OU=SpecOps,O=Capone\\, Inc,L=Chicago,ST=IL,C=US",
|
||||
"CN=bar.example.com,OU=Testsuite,O=Testing Corp,L=Hanover,ST=Lower Saxony,C=DE",
|
||||
}
|
||||
|
||||
const Test_TLSValidSingleCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const Test_TLSInvalidPEMData = `
|
||||
MIIF1zCCA7+gAwIBAgIUQdTcSHY2Sxd3Tq/v1eIEZPCNbOowDQYJKoZIhvcNAQEL
|
||||
BQAwezELMAkGA1UEBhMCREUxFTATBgNVBAgMDExvd2VyIFNheG9ueTEQMA4GA1UE
|
||||
BwwHSGFub3ZlcjEVMBMGA1UECgwMVGVzdGluZyBDb3JwMRIwEAYDVQQLDAlUZXN0
|
||||
c3VpdGUxGDAWBgNVBAMMD2Jhci5leGFtcGxlLmNvbTAeFw0xOTA3MDgxMzU2MTda
|
||||
Fw0yMDA3MDcxMzU2MTdaMHsxCzAJBgNVBAYTAkRFMRUwEwYDVQQIDAxMb3dlciBT
|
||||
YXhvbnkxEDAOBgNVBAcMB0hhbm92ZXIxFTATBgNVBAoMDFRlc3RpbmcgQ29ycDES
|
||||
MBAGA1UECwwJVGVzdHN1aXRlMRgwFgYDVQQDDA9iYXIuZXhhbXBsZS5jb20wggIi
|
||||
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCv4mHMdVUcafmaSHVpUM0zZWp5
|
||||
NFXfboxA4inuOkE8kZlbGSe7wiG9WqLirdr39Ts+WSAFA6oANvbzlu3JrEQ2CHPc
|
||||
CNQm6diPREFwcDPFCe/eMawbwkQAPVSHPts0UoRxnpZox5pn69ghncBR+jtvx+/u
|
||||
P6HdwW0qqTvfJnfAF1hBJ4oIk2AXiip5kkIznsAh9W6WRy6nTVCeetmIepDOGe0G
|
||||
ZJIRn/OfSz7NzKylfDCat2z3EAutyeT/5oXZoWOmGg/8T7pn/pR588GoYYKRQnp+
|
||||
YilqCPFX+az09EqqK/iHXnkdZ/Z2fCuU+9M/Zhrnlwlygl3RuVBI6xhm/ZsXtL2E
|
||||
Gxa61lNy6pyx5+hSxHEFEJshXLtioRd702VdLKxEOuYSXKeJDs1x9o6cJ75S6hko
|
||||
`
|
||||
|
||||
const Test_TLSInvalidSingleCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
XWyb96wrUlv+E8I=
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const Test_TLSValidMultiCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
XWyb96wrUlv+E8I=
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
// Taken from hack/ssh_known_hosts
|
||||
const Test_ValidSSHKnownHostsData = `
|
||||
# BitBucket
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
# GitHub
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
# GitLab
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
# Azure
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
`
|
||||
|
||||
const Test_InvalidSSHKnownHostsData = `
|
||||
bitbucket.org AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
# GitHub
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
# GitLab
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
# Azure
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
`
|
||||
|
||||
var Test_SSH_Hostname_Entries []string = []string{
|
||||
"bitbucket.org",
|
||||
"github.com",
|
||||
"gitlab.com",
|
||||
"gitlab.com",
|
||||
"gitlab.com",
|
||||
"ssh.dev.azure.com",
|
||||
"vs-ssh.visualstudio.com",
|
||||
}
|
||||
|
||||
var Test_SSH_Subtypes []string = []string{
|
||||
"ssh-rsa",
|
||||
"ssh-rsa",
|
||||
"ecdsa-sha2-nistp256",
|
||||
"ssh-ed25519",
|
||||
"ssh-rsa",
|
||||
"ssh-rsa",
|
||||
"ssh-rsa",
|
||||
}
|
||||
|
||||
var Test_TLS_Hostnames []string = []string{
|
||||
"test.example.com",
|
||||
"test.example.com",
|
||||
"github.com",
|
||||
}
|
||||
|
||||
const Test_NumSSHKnownHostsExpected = 7
|
||||
const Test_NumTLSCertificatesExpected = 3
|
||||
|
||||
func getCertClientset() *fake.Clientset {
|
||||
cm := v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: nil,
|
||||
}
|
||||
|
||||
sshCM := v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-ssh-known-hosts-cm",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"ssh_known_hosts": Test_ValidSSHKnownHostsData,
|
||||
},
|
||||
}
|
||||
|
||||
tlsCM := v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-tls-certs-cm",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"test.example.com": Test_TLSValidMultiCert,
|
||||
"gitlab.com": Test_TLSValidSingleCert,
|
||||
},
|
||||
}
|
||||
|
||||
return fake.NewSimpleClientset([]runtime.Object{&cm, &sshCM, &tlsCM}...)
|
||||
}
|
||||
|
||||
func Test_ListCertificate(t *testing.T) {
|
||||
clientset := getCertClientset()
|
||||
db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
|
||||
assert.NotNil(t, db)
|
||||
|
||||
// List all SSH known host entries from configuration.
|
||||
// Expected: List of 7 entries
|
||||
certList, err := db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "*",
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, len(certList.Items), Test_NumSSHKnownHostsExpected)
|
||||
for idx, entry := range certList.Items {
|
||||
assert.Equal(t, entry.ServerName, Test_SSH_Hostname_Entries[idx])
|
||||
assert.Equal(t, entry.CertSubType, Test_SSH_Subtypes[idx])
|
||||
}
|
||||
|
||||
// List all TLS certificates from configuration.
|
||||
// Expected: List of 3 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "*",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected)
|
||||
|
||||
// List all certificates using selector
|
||||
// Expected: List of 10 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "*",
|
||||
CertType: "*",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
|
||||
|
||||
// List all certificates using nil selector
|
||||
// Expected: List of 10 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), nil)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, len(certList.Items), Test_NumTLSCertificatesExpected+Test_NumSSHKnownHostsExpected)
|
||||
|
||||
// List all certificates matching a host name pattern
|
||||
// Expected: List of 4 entries, all with servername gitlab.com
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "gitlab.com",
|
||||
CertType: "*",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 4, len(certList.Items))
|
||||
for _, entry := range certList.Items {
|
||||
assert.Equal(t, "gitlab.com", entry.ServerName)
|
||||
}
|
||||
|
||||
// List all TLS certificates matching a host name pattern
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "gitlab.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
assert.Equal(t, "gitlab.com", certList.Items[0].ServerName)
|
||||
assert.Equal(t, "https", certList.Items[0].CertType)
|
||||
}
|
||||
|
||||
func Test_CreateSSHKnownHostEntries(t *testing.T) {
|
||||
clientset := getCertClientset()
|
||||
db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
|
||||
assert.NotNil(t, db)
|
||||
|
||||
// Valid known hosts entry
|
||||
certList, err := db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Check if it really was added
|
||||
// Result: List of 1 entry
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "foo.example.com",
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Existing cert, same data, no upsert
|
||||
// Result: no error, should return 0 added certificates
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
// Existing cert, different data, no upsert
|
||||
// Result: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Existing cert, different data, upsert
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="),
|
||||
},
|
||||
},
|
||||
}, true)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Invalid known hosts entry, case 1: key sub type missing
|
||||
// Result: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "bar.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Invalid known hosts entry, case 2: invalid base64 data
|
||||
// Result: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "bar.example.com",
|
||||
CertType: "ssh",
|
||||
CertData: []byte("ssh-rsa AAAAB3Nza1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
}
|
||||
|
||||
func Test_CreateTLSCertificates(t *testing.T) {
|
||||
clientset := getCertClientset()
|
||||
db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
|
||||
assert.NotNil(t, db)
|
||||
|
||||
// Valid TLS certificate
|
||||
// Expected: List of 1 entry
|
||||
certList, err := db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSValidSingleCert),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Check if it really was added
|
||||
// Result: Return new certificate
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "foo.example.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Valid TLS certificates, multiple PEMs in data
|
||||
// Expected: List of 2 entry
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "bar.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSValidMultiCert),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 2, len(certList.Items))
|
||||
|
||||
// Check if it really was added
|
||||
// Result: Return new certificate
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "bar.example.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 2, len(certList.Items))
|
||||
|
||||
// Valid TLS certificate, existing cert, same data, no upsert
|
||||
// Expected: List of 0 entry
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSValidSingleCert),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
// Valid TLS certificate, existing cert, different data, no upsert
|
||||
// Expected: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSValidMultiCert),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Valid TLS certificate, existing cert, different data, upsert
|
||||
// Expected: List of 2 entries
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "foo.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSValidMultiCert),
|
||||
},
|
||||
},
|
||||
}, true)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 2, len(certList.Items))
|
||||
|
||||
// Check if upsert was successful
|
||||
// Expected: List of 2 entries, matching hostnames & cert types
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "foo.example.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 2, len(certList.Items))
|
||||
for _, entry := range certList.Items {
|
||||
assert.Equal(t, "foo.example.com", entry.ServerName)
|
||||
assert.Equal(t, "https", entry.CertType)
|
||||
}
|
||||
|
||||
// Invalid PEM data, new cert
|
||||
// Expected: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "baz.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSInvalidPEMData),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Valid PEM data, new cert, but invalid certificate
|
||||
// Expected: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "baz.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSInvalidSingleCert),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Invalid PEM data, existing cert, upsert
|
||||
// Expected: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "baz.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSInvalidPEMData),
|
||||
},
|
||||
},
|
||||
}, true)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
// Valid PEM data, existing cert, but invalid certificate, upsert
|
||||
// Expected: Error
|
||||
certList, err = db.CreateRepoCertificate(context.Background(), &v1alpha1.RepositoryCertificateList{
|
||||
Items: []v1alpha1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: "baz.example.com",
|
||||
CertType: "https",
|
||||
CertData: []byte(Test_TLSInvalidSingleCert),
|
||||
},
|
||||
},
|
||||
}, true)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, certList)
|
||||
|
||||
}
|
||||
|
||||
func Test_RemoveSSHKnownHosts(t *testing.T) {
|
||||
clientset := getCertClientset()
|
||||
db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
|
||||
assert.NotNil(t, db)
|
||||
|
||||
// Remove single SSH known hosts entry by hostname
|
||||
// Expected: List of 1 entry
|
||||
certList, err := db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "github.com",
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Check whether entry was really removed
|
||||
// Expected: List of 0 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "github.com",
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
// Remove single SSH known hosts entry by sub type
|
||||
// Expected: List of 1 entry
|
||||
certList, err = db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
CertType: "ssh",
|
||||
CertSubType: "ssh-ed25519",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Check whether entry was really removed
|
||||
// Expected: List of 0 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
CertType: "ssh",
|
||||
CertSubType: "ssh-ed25519",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
// Remove all remaining SSH known hosts entries
|
||||
// Expected: List of 5 entry
|
||||
certList, err = db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 5, len(certList.Items))
|
||||
|
||||
// Check whether the entries were really removed
|
||||
// Expected: List of 0 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
CertType: "ssh",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
}
|
||||
|
||||
func Test_RemoveTLSCertificates(t *testing.T) {
|
||||
clientset := getCertClientset()
|
||||
db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
|
||||
assert.NotNil(t, db)
|
||||
|
||||
// Remove single TLS certificate entry by hostname
|
||||
// Expected: List of 1 entry
|
||||
certList, err := db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "gitlab.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 1, len(certList.Items))
|
||||
|
||||
// Check whether entry was really removed
|
||||
// Expected: List of 0 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "gitlab.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
// Remove all TLS certificate entry for hostname
|
||||
// Expected: List of 2 entry
|
||||
certList, err = db.RemoveRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "test.example.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 2, len(certList.Items))
|
||||
|
||||
// Check whether entries were really removed
|
||||
// Expected: List of 0 entries
|
||||
certList, err = db.ListRepoCertificates(context.Background(), &CertificateListSelector{
|
||||
HostNamePattern: "test.example.com",
|
||||
CertType: "https",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, certList)
|
||||
assert.Equal(t, 0, len(certList.Items))
|
||||
|
||||
}
|
||||
|
|
@ -37,6 +37,13 @@ type ArgoDB interface {
|
|||
|
||||
// ListHelmRepoURLs lists configured helm repositories
|
||||
ListHelmRepos(ctx context.Context) ([]*appv1.HelmRepository, error)
|
||||
|
||||
// ListRepoCerticifates lists all configured certificates
|
||||
ListRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appv1.RepositoryCertificateList, error)
|
||||
// CreateRepoCertificate creates a new certificate entry
|
||||
CreateRepoCertificate(ctx context.Context, certificate *appv1.RepositoryCertificateList, upsert bool) (*appv1.RepositoryCertificateList, error)
|
||||
// CreateRepoCertificate creates a new certificate entry
|
||||
RemoveRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appv1.RepositoryCertificateList, error)
|
||||
}
|
||||
|
||||
type db struct {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ func getClientset(config map[string]string, objects ...runtime.Object) *fake.Cli
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: config,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ func (db *db) CreateRepository(ctx context.Context, r *appsv1.Repository) (*apps
|
|||
|
||||
repoInfo := settings.RepoCredentials{
|
||||
URL: r.Repo,
|
||||
InsecureIgnoreHostKey: r.InsecureIgnoreHostKey,
|
||||
InsecureIgnoreHostKey: (r.InsecureIgnoreHostKey || r.Insecure),
|
||||
Insecure: (r.InsecureIgnoreHostKey || r.Insecure),
|
||||
}
|
||||
err = db.updateSecrets(&repoInfo, r)
|
||||
if err != nil {
|
||||
|
|
@ -121,6 +122,7 @@ func (db *db) credentialsToRepository(repoInfo settings.RepoCredentials) (*appsv
|
|||
repo := &appsv1.Repository{
|
||||
Repo: repoInfo.URL,
|
||||
InsecureIgnoreHostKey: repoInfo.InsecureIgnoreHostKey,
|
||||
Insecure: repoInfo.Insecure,
|
||||
}
|
||||
err := db.unmarshalFromSecretsStr(map[*string]*apiv1.SecretKeySelector{
|
||||
&repo.Username: repoInfo.UsernameSecret,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
|
@ -15,10 +18,11 @@ import (
|
|||
"gopkg.in/src-d/go-git.v4/config"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
|
||||
githttp "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
|
||||
ssh2 "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
|
||||
"gopkg.in/src-d/go-git.v4/storage/memory"
|
||||
|
||||
certutil "github.com/argoproj/argo-cd/util/cert"
|
||||
argoconfig "github.com/argoproj/argo-cd/util/config"
|
||||
)
|
||||
|
||||
|
|
@ -44,14 +48,19 @@ type Client interface {
|
|||
// ClientFactory is a factory of Git Clients
|
||||
// Primarily used to support creation of mock git clients during unit testing
|
||||
type ClientFactory interface {
|
||||
NewClient(repoURL, path, username, password, sshPrivateKey string, insecureIgnoreHostKey bool) (Client, error)
|
||||
NewClient(repoURL, path, username, password, sshPrivateKey string, insecure bool) (Client, error)
|
||||
}
|
||||
|
||||
// nativeGitClient implements Client interface using git CLI
|
||||
type nativeGitClient struct {
|
||||
// URL of the repository
|
||||
repoURL string
|
||||
root string
|
||||
creds Creds
|
||||
// Root path of repository
|
||||
root string
|
||||
// Authenticator credentials for private repositories
|
||||
creds Creds
|
||||
// Whether to connect insecurely to repository, e.g. don't verify certificate
|
||||
insecure bool
|
||||
}
|
||||
|
||||
type factory struct{}
|
||||
|
|
@ -60,23 +69,90 @@ func NewFactory() ClientFactory {
|
|||
return &factory{}
|
||||
}
|
||||
|
||||
func (f *factory) NewClient(rawRepoURL, path, username, password, sshPrivateKey string, insecureIgnoreHostKey bool) (Client, error) {
|
||||
func (f *factory) NewClient(rawRepoURL, path, username, password, sshPrivateKey string, insecure bool) (Client, error) {
|
||||
var creds Creds
|
||||
if sshPrivateKey != "" {
|
||||
creds = SSHCreds{sshPrivateKey, insecureIgnoreHostKey}
|
||||
creds = SSHCreds{sshPrivateKey, insecure}
|
||||
} else if username != "" || password != "" {
|
||||
creds = HTTPSCreds{username, password}
|
||||
} else {
|
||||
creds = NopCreds{}
|
||||
}
|
||||
|
||||
// We need a custom HTTP client for go-git when we want to skip validation
|
||||
// of the server's TLS certificate (--insecure-ignore-server-cert). Since
|
||||
// this change is permanent to go-git Client during runtime, we need to
|
||||
// explicitly replace it with default client for repositories without the
|
||||
// insecure flag set.
|
||||
//if IsHTTPSURL(rawRepoURL) {
|
||||
// gitclient.InstallProtocol("https", githttp.NewClient(getRepoHTTPClient(rawRepoURL, insecure)))
|
||||
//}
|
||||
client := nativeGitClient{
|
||||
repoURL: rawRepoURL,
|
||||
root: path,
|
||||
creds: creds,
|
||||
repoURL: rawRepoURL,
|
||||
root: path,
|
||||
creds: creds,
|
||||
insecure: insecure,
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// Returns a HTTP client object suitable for go-git to use using the following
|
||||
// pattern:
|
||||
// - If insecure is true, always returns a client with certificate verification
|
||||
// turned off.
|
||||
// - If one or more custom certificates are stored for the repository, returns
|
||||
// a client with those certificates in the list of root CAs used to verify
|
||||
// the server's certificate.
|
||||
// - Otherwise (and on non-fatal errors), a default HTTP client is returned.
|
||||
func getRepoHTTPClient(repoURL string, insecure bool) transport.Transport {
|
||||
// Default HTTP client
|
||||
var customHTTPClient transport.Transport = githttp.NewClient(&http.Client{})
|
||||
|
||||
if insecure {
|
||||
customHTTPClient = githttp.NewClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
// 15 second timeout
|
||||
Timeout: 15 * time.Second,
|
||||
|
||||
// don't follow redirect
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
})
|
||||
} else {
|
||||
parsedURL, err := url.Parse(repoURL)
|
||||
if err != nil {
|
||||
return customHTTPClient
|
||||
}
|
||||
serverCertificatePem, err := certutil.GetCertificateForConnect(parsedURL.Host)
|
||||
if err != nil {
|
||||
return customHTTPClient
|
||||
} else if len(serverCertificatePem) > 0 {
|
||||
certPool := certutil.GetCertPoolFromPEMData(serverCertificatePem)
|
||||
customHTTPClient = githttp.NewClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: certPool,
|
||||
},
|
||||
},
|
||||
// 15 second timeout
|
||||
Timeout: 15 * time.Second,
|
||||
// don't follow redirect
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
})
|
||||
}
|
||||
// else no custom certificate stored.
|
||||
}
|
||||
|
||||
return customHTTPClient
|
||||
}
|
||||
|
||||
func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
|
||||
switch creds := creds.(type) {
|
||||
case SSHCreds:
|
||||
|
|
@ -94,7 +170,7 @@ func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
|
|||
}
|
||||
return auth, nil
|
||||
case HTTPSCreds:
|
||||
auth := http.BasicAuth{Username: creds.username, Password: creds.password}
|
||||
auth := githttp.BasicAuth{Username: creds.username, Password: creds.password}
|
||||
return &auth, nil
|
||||
}
|
||||
return nil, nil
|
||||
|
|
@ -188,7 +264,8 @@ func (m *nativeGitClient) LsRemote(revision string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
refs, err := remote.List(&git.ListOptions{Auth: auth})
|
||||
//refs, err := remote.List(&git.ListOptions{Auth: auth})
|
||||
refs, err := listRemote(remote, &git.ListOptions{Auth: auth}, m.insecure)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -291,11 +368,30 @@ func (m *nativeGitClient) runCredentialedCmd(command string, args ...string) (st
|
|||
}
|
||||
|
||||
func (m *nativeGitClient) runCmdOutput(cmd *exec.Cmd) (string, error) {
|
||||
log.Debug(strings.Join(cmd.Args, " "))
|
||||
cmd.Dir = m.root
|
||||
cmd.Env = append(cmd.Env, os.Environ()...)
|
||||
cmd.Env = append(cmd.Env, "HOME=/dev/null")
|
||||
cmd.Env = append(cmd.Env, "GIT_CONFIG_NOSYSTEM=true")
|
||||
cmd.Env = append(cmd.Env, "GIT_CONFIG_NOGLOBAL=true")
|
||||
// For HTTPS repositories, we need to consider insecure repositories as well
|
||||
// as custom CA bundles from the cert database.
|
||||
if IsHTTPSURL(m.repoURL) {
|
||||
if m.insecure {
|
||||
cmd.Env = append(cmd.Env, "GIT_SSL_NO_VERIFY=true")
|
||||
} else {
|
||||
parsedURL, err := url.Parse(m.repoURL)
|
||||
// We don't fail if we cannot parse the URL, but log a warning in that
|
||||
// case. And we execute the command in a verbatim way.
|
||||
if err != nil {
|
||||
log.Warnf("runCmdOutput: Could not parse repo URL '%s'", m.repoURL)
|
||||
} else {
|
||||
caPath, err := certutil.GetCertBundlePathForRepository(parsedURL.Host)
|
||||
if err == nil && caPath != "" {
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_SSL_CAINFO=%s", caPath))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Debug(strings.Join(cmd.Args, " "))
|
||||
return argoexec.RunCommandExt(cmd, argoconfig.CmdOpts())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ func removeSuffix(s, suffix string) string {
|
|||
var (
|
||||
commitSHARegex = regexp.MustCompile("^[0-9A-Fa-f]{40}$")
|
||||
sshURLRegex = regexp.MustCompile("^(ssh://)?([^/@:]*?)@.*")
|
||||
httpsURLRegex = regexp.MustCompile("^(https://).*")
|
||||
)
|
||||
|
||||
// IsCommitSHA returns whether or not a string is a 40 character SHA-1
|
||||
|
|
@ -71,6 +72,11 @@ func IsSSHURL(url string) (bool, string) {
|
|||
return false, ""
|
||||
}
|
||||
|
||||
// IsHTTPSURL returns true if supplied URL is HTTPS URL
|
||||
func IsHTTPSURL(url string) bool {
|
||||
return httpsURLRegex.MatchString(url)
|
||||
}
|
||||
|
||||
// TestRepo tests if a repo exists and is accessible with the given credentials
|
||||
func TestRepo(repo, username, password string, sshPrivateKey string, insecureIgnoreHostKey bool) error {
|
||||
clnt, err := NewFactory().NewClient(repo, "", username, password, sshPrivateKey, insecureIgnoreHostKey)
|
||||
|
|
|
|||
74
util/git/workaround.go
Normal file
74
util/git/workaround.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/transport/client"
|
||||
"gopkg.in/src-d/go-git.v4/utils/ioutil"
|
||||
)
|
||||
|
||||
// Below is a workaround for https://github.com/src-d/go-git/issues/1177: the `github.com/src-d/go-git` does not support disable SSL cert verification is a single repo.
|
||||
// As workaround methods `newUploadPackSession`, `newClient` and `listRemote` were copied from https://github.com/src-d/go-git/blob/master/remote.go and modified to use
|
||||
// transport with InsecureSkipVerify flag is verification should be disabled.
|
||||
|
||||
func newUploadPackSession(url string, auth transport.AuthMethod, insecureSkipTLSVerify bool) (transport.UploadPackSession, error) {
|
||||
c, ep, err := newClient(url, insecureSkipTLSVerify)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.NewUploadPackSession(ep, auth)
|
||||
}
|
||||
|
||||
func newClient(url string, insecureSkipTLSVerify bool) (transport.Transport, *transport.Endpoint, error) {
|
||||
ep, err := transport.NewEndpoint(url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var c transport.Transport
|
||||
// For HTTPS repositories, we get a custom Transport. Everything else will
|
||||
// be default.
|
||||
if IsHTTPSURL(url) {
|
||||
c = getRepoHTTPClient(url, insecureSkipTLSVerify)
|
||||
} else {
|
||||
c, err = client.NewClient(ep)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return c, ep, err
|
||||
}
|
||||
|
||||
func listRemote(r *git.Remote, o *git.ListOptions, insecureSkipTLSVerify bool) (rfs []*plumbing.Reference, err error) {
|
||||
s, err := newUploadPackSession(r.Config().URLs[0], o.Auth, insecureSkipTLSVerify)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer ioutil.CheckClose(s, &err)
|
||||
|
||||
ar, err := s.AdvertisedReferences()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allRefs, err := ar.AllReferences()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refs, err := allRefs.IterReferences()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resultRefs []*plumbing.Reference
|
||||
_ = refs.ForEach(func(ref *plumbing.Reference) error {
|
||||
resultRefs = append(resultRefs, ref)
|
||||
return nil
|
||||
})
|
||||
|
||||
return resultRefs, nil
|
||||
}
|
||||
|
|
@ -27,6 +27,9 @@ func TestSessionManager(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: "argocd",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
}, &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
|
|
|||
|
|
@ -80,12 +80,20 @@ type OIDCConfig struct {
|
|||
RequestedScopes []string `json:"requestedScopes,omitempty"`
|
||||
}
|
||||
|
||||
// Credentials for accessing a Git repository
|
||||
type RepoCredentials struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
UsernameSecret *apiv1.SecretKeySelector `json:"usernameSecret,omitempty"`
|
||||
PasswordSecret *apiv1.SecretKeySelector `json:"passwordSecret,omitempty"`
|
||||
SSHPrivateKeySecret *apiv1.SecretKeySelector `json:"sshPrivateKeySecret,omitempty"`
|
||||
InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty"`
|
||||
// The URL to the repository
|
||||
URL string `json:"url,omitempty"`
|
||||
// Name of the secret storing the username used to access the repo
|
||||
UsernameSecret *apiv1.SecretKeySelector `json:"usernameSecret,omitempty"`
|
||||
// Name of the secret storing the password used to access the repo
|
||||
PasswordSecret *apiv1.SecretKeySelector `json:"passwordSecret,omitempty"`
|
||||
// Name of the secret storing the SSH private key used to access the repo
|
||||
SSHPrivateKeySecret *apiv1.SecretKeySelector `json:"sshPrivateKeySecret,omitempty"`
|
||||
// Whether to connect the repository in an insecure way (deprecated)
|
||||
InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty"`
|
||||
// Whether to connect the repository in an insecure way
|
||||
Insecure bool `json:"insecure,omitempty"`
|
||||
}
|
||||
|
||||
type HelmRepoCredentials struct {
|
||||
|
|
@ -196,6 +204,21 @@ func (mgr *SettingsManager) getConfigMap() (*apiv1.ConfigMap, error) {
|
|||
return argoCDCM, err
|
||||
}
|
||||
|
||||
// Returns the ConfigMap with the given name from the cluster.
|
||||
// The ConfigMap must be labeled with "app.kubernetes.io/part-of: argocd" in
|
||||
// order to be retrievable.
|
||||
func (mgr *SettingsManager) GetNamedConfigMap(configMapName string) (*apiv1.ConfigMap, error) {
|
||||
err := mgr.ensureSynced(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configMap, err := mgr.configmaps.ConfigMaps(mgr.namespace).Get(configMapName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return configMap, err
|
||||
}
|
||||
|
||||
func (mgr *SettingsManager) GetResourcesFilter() (*ResourcesFilter, error) {
|
||||
argoCDCM, err := mgr.getConfigMap()
|
||||
if err != nil {
|
||||
|
|
@ -372,8 +395,9 @@ func (mgr *SettingsManager) GetSettings() (*ArgoCDSettings, error) {
|
|||
|
||||
func (mgr *SettingsManager) initialize(ctx context.Context) error {
|
||||
tweakConfigMap := func(options *metav1.ListOptions) {
|
||||
cmFieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", common.ArgoCDConfigMapName))
|
||||
options.FieldSelector = cmFieldSelector.String()
|
||||
//cmFieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", common.ArgoCDConfigMapName))
|
||||
cmLabelSelector := fields.ParseSelectorOrDie("app.kubernetes.io/part-of=argocd")
|
||||
options.LabelSelector = cmLabelSelector.String()
|
||||
}
|
||||
|
||||
cmInformer := v1.NewFilteredConfigMapInformer(mgr.clientset, mgr.namespace, 3*time.Minute, cache.Indexers{}, tweakConfigMap)
|
||||
|
|
@ -616,6 +640,51 @@ func (mgr *SettingsManager) SaveSettings(settings *ArgoCDSettings) error {
|
|||
return mgr.ResyncInformers()
|
||||
}
|
||||
|
||||
// Save the SSH known host data into the corresponding ConfigMap
|
||||
func (mgr *SettingsManager) SaveSSHKnownHostsData(ctx context.Context, knownHostsList []string) error {
|
||||
err := mgr.ensureSynced(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certCM, err := mgr.GetNamedConfigMap(common.ArgoCDKnownHostsConfigMapName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if certCM.Data == nil {
|
||||
certCM.Data = make(map[string]string)
|
||||
}
|
||||
|
||||
certCM.Data["ssh_known_hosts"] = strings.Join(knownHostsList, "\n")
|
||||
_, err = mgr.clientset.CoreV1().ConfigMaps(mgr.namespace).Update(certCM)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return mgr.ResyncInformers()
|
||||
}
|
||||
|
||||
func (mgr *SettingsManager) SaveTLSCertificateData(ctx context.Context, tlsCertificates map[string]string) error {
|
||||
err := mgr.ensureSynced(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certCM, err := mgr.GetNamedConfigMap(common.ArgoCDTLSCertsConfigMapName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certCM.Data = tlsCertificates
|
||||
_, err = mgr.clientset.CoreV1().ConfigMaps(mgr.namespace).Update(certCM)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return mgr.ResyncInformers()
|
||||
}
|
||||
|
||||
// NewSettingsManager generates a new SettingsManager pointer and returns it
|
||||
func NewSettingsManager(ctx context.Context, clientset kubernetes.Interface, namespace string) *SettingsManager {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ func TestGetRepositories(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"repositories": "\n - url: http://foo\n",
|
||||
|
|
@ -34,6 +37,9 @@ func TestSaveRepositories(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
})
|
||||
settingsManager := NewSettingsManager(context.Background(), kubeClient, "default")
|
||||
|
|
@ -49,6 +55,9 @@ func TestGetRepositoryCredentials(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"repository.credentials": "\n - url: http://foo\n",
|
||||
|
|
@ -65,6 +74,9 @@ func TestGetResourceFilter(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"resource.exclusions": "\n - apiGroups: [\"group1\"]\n kinds: [\"kind1\"]\n clusters: [\"cluster1\"]\n",
|
||||
|
|
@ -85,6 +97,9 @@ func TestGetConfigManagementPlugins(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"configManagementPlugins": `
|
||||
|
|
@ -110,6 +125,9 @@ func TestGetAppInstanceLabelKey(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"application.instanceLabelKey": "testLabel",
|
||||
|
|
@ -126,6 +144,9 @@ func TestGetResourceOverrides(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"resource.customizations": `
|
||||
|
|
@ -152,6 +173,9 @@ func TestGetHelmRepositories(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"helm.repositories": "\n - url: http://foo\n",
|
||||
|
|
@ -169,6 +193,9 @@ func TestGetGoogleAnalytics(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"ga.trackingid": "123",
|
||||
|
|
|
|||
Loading…
Reference in a new issue