From 34ae088dc064be78744886fff32e956cfd475591 Mon Sep 17 00:00:00 2001 From: Max Shaposhnyk Date: Mon, 13 May 2024 13:15:25 +0300 Subject: [PATCH] Add scm secrets into credentials lookup mechnism & fix gitlab client creation (#939) --------- Signed-off-by: Max Shaposhnyk --- .../gitlab/downloadfilecapability.go | 5 +++ .../gitlab/gitlabclientbuilder.go | 8 ++++- pkg/serviceprovider/lookup.go | 35 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pkg/serviceprovider/gitlab/downloadfilecapability.go b/pkg/serviceprovider/gitlab/downloadfilecapability.go index 9e600f94d..b29e7fc66 100644 --- a/pkg/serviceprovider/gitlab/downloadfilecapability.go +++ b/pkg/serviceprovider/gitlab/downloadfilecapability.go @@ -20,6 +20,9 @@ import ( "errors" "fmt" "net/http" + "strings" + + "github.com/redhat-appstudio/remote-secret/pkg/logs" api "github.com/redhat-appstudio/service-provider-integration-operator/api/v1beta1" "github.com/redhat-appstudio/service-provider-integration-operator/pkg/serviceprovider" @@ -71,6 +74,8 @@ func (f downloadFileCapability) DownloadFile(ctx context.Context, request api.SP refOption = gitlab.GetFileOptions{Ref: gitlab.Ptr("HEAD")} } + lg.V(logs.DebugLevel).Info("Downloading file", "owner", owner, "project", project, "filePath", request.FilePath, "ref", refOption.Ref) + request.FilePath = strings.TrimPrefix(request.FilePath, "/") file, resp, err := glClient.RepositoryFiles.GetFile(owner+"/"+project, request.FilePath, &refOption) if err != nil { // unfortunately, GitLab library closes the response body, so it is cannot be read diff --git a/pkg/serviceprovider/gitlab/gitlabclientbuilder.go b/pkg/serviceprovider/gitlab/gitlabclientbuilder.go index 39dc0016c..e698048ad 100644 --- a/pkg/serviceprovider/gitlab/gitlabclientbuilder.go +++ b/pkg/serviceprovider/gitlab/gitlabclientbuilder.go @@ -34,7 +34,13 @@ type gitlabClientBuilder struct { var _ serviceprovider.AuthenticatedClientBuilder[gitlab.Client] = (*gitlabClientBuilder)(nil) func (builder gitlabClientBuilder) CreateAuthenticatedClient(ctx context.Context, credentials serviceprovider.Credentials) (*gitlab.Client, error) { - client, err := gitlab.NewOAuthClient(credentials.Token, gitlab.WithHTTPClient(builder.httpClient), gitlab.WithBaseURL(builder.gitlabBaseUrl)) + var client *gitlab.Client + var err error + if credentials.Username == "" { + client, err = gitlab.NewClient(credentials.Token, gitlab.WithHTTPClient(builder.httpClient), gitlab.WithBaseURL(builder.gitlabBaseUrl)) + } else { + client, err = gitlab.NewBasicAuthClient(credentials.Username, credentials.Token, gitlab.WithHTTPClient(builder.httpClient), gitlab.WithBaseURL(builder.gitlabBaseUrl)) + } if err != nil { return nil, fmt.Errorf("failed to created new authenticated GitLab client: %w", err) } diff --git a/pkg/serviceprovider/lookup.go b/pkg/serviceprovider/lookup.go index 5c7b4a328..b78b5f897 100644 --- a/pkg/serviceprovider/lookup.go +++ b/pkg/serviceprovider/lookup.go @@ -42,6 +42,11 @@ import ( var missingTargetError = errors.New("found RemoteSecret does not have a target in the SPIAccessCheck's namespace, this should not happen") var accessTokenNotFoundError = errors.New("token data is not found in token storage") +const ( + ScmCredentialsSecretLabel = "appstudio.redhat.com/credentials" + ScmSecretHostnameLabel = "appstudio.redhat.com/scm.host" +) + // GenericLookup implements a token lookup in a generic way such that the users only need to provide a function // to provide a service-provider-specific "state" of the token and a "filter" function that uses the token and its // state to match it against a binding @@ -183,6 +188,14 @@ func (l GenericLookup) LookupCredentials(ctx context.Context, cl client.Client, if err != nil { return nil, err } + + if secret == nil { + secret, err = l.lookupSCMSecret(ctx, cl, matchable) + if err != nil { + return nil, err + } + } + if secret == nil { return nil, nil } @@ -193,6 +206,28 @@ func (l GenericLookup) LookupCredentials(ctx context.Context, cl client.Client, }, nil } +func (l GenericLookup) lookupSCMSecret(ctx context.Context, cl client.Client, matchable Matchable) (*v1.Secret, error) { + lg := log.FromContext(ctx) + repoUrl, err := l.RepoUrlParser(matchable.RepoUrl()) + if err != nil { + return nil, fmt.Errorf("error parsing the repo URL %s: %w", matchable.RepoUrl(), err) + } + secretList := &v1.SecretList{} + opts := client.ListOption(&client.MatchingLabels{ + ScmCredentialsSecretLabel: "scm", + ScmSecretHostnameLabel: repoUrl.Host, + }) + + if err := cl.List(ctx, secretList, client.InNamespace(matchable.ObjNamespace()), opts); err != nil { + return nil, fmt.Errorf("failed to list SCM secrets in %s namespace: %w", matchable.ObjNamespace(), err) + } + if len(secretList.Items) > 0 { + lg.V(logs.DebugLevel).Info("found SCM secret", "name", secretList.Items[0].Name) + return &secretList.Items[0], nil + } + return nil, nil +} + // lookupRemoteSecrets searches for RemoteSecrets with RSServiceProviderHostLabel in the same namespaces matchable and // filters them using GenericLookup's RemoteSecretFilter. func (l GenericLookup) lookupRemoteSecrets(ctx context.Context, cl client.Client, matchable Matchable) ([]v1beta1.RemoteSecret, error) {