diff --git a/config/resolvers/bundleresolver-config.yaml b/config/resolvers/bundleresolver-config.yaml index d48372ddd11..31d9e89a805 100644 --- a/config/resolvers/bundleresolver-config.yaml +++ b/config/resolvers/bundleresolver-config.yaml @@ -23,6 +23,6 @@ metadata: app.kubernetes.io/part-of: tekton-pipelines data: # the default service account name to use for bundle requests. - default-service-account: "default" + default-secret: "default-secret" # The default layer kind in the bundle image. default-kind: "task" diff --git a/docs/bundle-resolver.md b/docs/bundle-resolver.md index 468b0003887..4101bf03cc3 100644 --- a/docs/bundle-resolver.md +++ b/docs/bundle-resolver.md @@ -15,7 +15,7 @@ This Resolver responds to type `bundles`. | Param Name | Description | Example Value | |------------------|-------------------------------------------------------------------------------|------------------------------------------------------------| -| `serviceAccount` | The name of the service account to use when constructing registry credentials | `default` | +| `secret` | The name of the secret to use when constructing registry credentials | `default` | | `bundle` | The bundle url pointing at the image to fetch | `gcr.io/tekton-releases/catalog/upstream/golang-build:0.1` | | `name` | The name of the resource to pull out of the bundle | `golang-build` | | `kind` | The resource kind to pull out of the bundle | `task` | @@ -24,7 +24,7 @@ This Resolver responds to type `bundles`. - A cluster running Tekton Pipeline v0.41.0 or later. - The [built-in remote resolvers installed](./install.md#installing-and-configuring-remote-task-and-pipeline-resolution). -- The `enable-bundles-resolver` feature flag in the `resolvers-feature-flags` ConfigMap +- The `enable-bundles-resolver` feature flag in the `resolvers-feature-flags` ConfigMap in the `tekton-pipelines-resolvers` namespace set to `true`. - [Beta features](./additional-configs.md#beta-features) enabled. @@ -38,7 +38,7 @@ for the name, namespace and defaults that the resolver ships with. | Option Name | Description | Example Values | |---------------------------|--------------------------------------------------------------|-----------------------| -| `default-service-account` | The default service account name to use for bundle requests. | `default`, `someuser` | +| `default-secret` | The default secret name to use for bundle requests. | `default`, `registry-secret` | | `default-kind` | The default layer kind in the bundle image. | `task`, `pipeline` | ## Usage diff --git a/pkg/resolution/resolver/bundle/bundle.go b/pkg/resolution/resolver/bundle/bundle.go index 590135374d4..e8f2ddac41b 100644 --- a/pkg/resolution/resolver/bundle/bundle.go +++ b/pkg/resolution/resolver/bundle/bundle.go @@ -37,10 +37,10 @@ const ( // RequestOptions are the options used to request a resource from // a remote bundle. type RequestOptions struct { - ServiceAccount string - Bundle string - EntryName string - Kind string + ImagePullSecret string + Bundle string + EntryName string + Kind string } // ResolvedResource wraps the content of a matched entry in a bundle. diff --git a/pkg/resolution/resolver/bundle/config.go b/pkg/resolution/resolver/bundle/config.go index e46a3151334..32f39778b47 100644 --- a/pkg/resolution/resolver/bundle/config.go +++ b/pkg/resolution/resolver/bundle/config.go @@ -16,9 +16,8 @@ package bundle const ( // ConfigMapName is the bundle resolver's config map ConfigMapName = "bundleresolver-config" - // ConfigServiceAccount is the configuration field name for controlling - // the Service Account name to use for bundle requests. - ConfigServiceAccount = "default-service-account" + // ConfigSecret is the configuration name to use for bundle requests. + ConfigSecret = "default-secret" // ConfigKind is the configuration field name for controlling // what the layer name in the bundle image is. ConfigKind = "default-kind" diff --git a/pkg/resolution/resolver/bundle/params.go b/pkg/resolution/resolver/bundle/params.go index 207a959ad4b..5aed6cc5de2 100644 --- a/pkg/resolution/resolver/bundle/params.go +++ b/pkg/resolution/resolver/bundle/params.go @@ -22,9 +22,9 @@ import ( "github.com/tektoncd/pipeline/pkg/resolution/resolver/framework" ) -// ParamServiceAccount is the parameter defining what service -// account name to use for bundle requests. -const ParamServiceAccount = "serviceAccount" +// ParamImagePullSecret is the parameter defining what secret +// name to use for bundle requests. +const ParamImagePullSecret = "secret" // ParamBundle is the parameter defining what the bundle image url is. const ParamBundle = "bundle" @@ -48,16 +48,16 @@ func OptionsFromParams(ctx context.Context, params []pipelinev1.Param) (RequestO paramsMap[p.Name] = p.Value } - saVal, ok := paramsMap[ParamServiceAccount] - sa := "" - if !ok || saVal.StringVal == "" { - if saString, ok := conf[ConfigServiceAccount]; ok { - sa = saString + secretVal, ok := paramsMap[ParamImagePullSecret] + secret := "" + if !ok || secretVal.StringVal == "" { + if saString, ok := conf[ConfigSecret]; ok { + secret = saString } else { return opts, fmt.Errorf("default Service Account was not set during installation of the bundle resolver") } } else { - sa = saVal.StringVal + secret = secretVal.StringVal } bundleVal, ok := paramsMap[ParamBundle] @@ -85,7 +85,7 @@ func OptionsFromParams(ctx context.Context, params []pipelinev1.Param) (RequestO kind = kindVal.StringVal } - opts.ServiceAccount = sa + opts.ImagePullSecret = secret opts.Bundle = bundleVal.StringVal opts.EntryName = nameVal.StringVal opts.Kind = kind diff --git a/pkg/resolution/resolver/bundle/resolver.go b/pkg/resolution/resolver/bundle/resolver.go index 3cd270a00b6..9be3724ad22 100644 --- a/pkg/resolution/resolver/bundle/resolver.go +++ b/pkg/resolution/resolver/bundle/resolver.go @@ -22,6 +22,7 @@ import ( "time" "github.com/google/go-containerregistry/pkg/authn/k8schain" + kauth "github.com/google/go-containerregistry/pkg/authn/kubernetes" resolverconfig "github.com/tektoncd/pipeline/pkg/apis/config/resolver" pipelinev1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/resolution/common" @@ -94,10 +95,14 @@ func (r *Resolver) Resolve(ctx context.Context, params []pipelinev1.Param) (fram return nil, err } namespace := common.RequestNamespace(ctx) - kc, _ := k8schain.New(ctx, r.kubeClientSet, k8schain.Options{ + kc, err := k8schain.New(ctx, r.kubeClientSet, k8schain.Options{ Namespace: namespace, - ServiceAccountName: opts.ServiceAccount, + ImagePullSecrets: []string{opts.ImagePullSecret}, + ServiceAccountName: kauth.NoServiceAccount, }) + if err != nil { + return nil, err + } ctx, cancelFn := context.WithTimeout(ctx, timeoutDuration) defer cancelFn() return GetEntry(ctx, kc, opts) diff --git a/pkg/resolution/resolver/bundle/resolver_test.go b/pkg/resolution/resolver/bundle/resolver_test.go index d0917374115..9f48f9cc7bd 100644 --- a/pkg/resolution/resolver/bundle/resolver_test.go +++ b/pkg/resolution/resolver/bundle/resolver_test.go @@ -18,6 +18,7 @@ package bundle_test import ( "context" + "errors" "fmt" "net/http/httptest" "net/url" @@ -39,8 +40,10 @@ import ( "github.com/tektoncd/pipeline/test" "github.com/tektoncd/pipeline/test/diff" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + ktesting "k8s.io/client-go/testing" "knative.dev/pkg/system" _ "knative.dev/pkg/system/testing" // Setup system.Namespace() "sigs.k8s.io/yaml" @@ -73,7 +76,7 @@ func TestValidateParams(t *testing.T) { Name: bundle.ParamBundle, Value: *pipelinev1.NewStructuredValues("bar"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} @@ -91,7 +94,7 @@ func TestValidateParams(t *testing.T) { Name: bundle.ParamBundle, Value: *pipelinev1.NewStructuredValues("bar"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} if err := resolver.ValidateParams(context.Background(), paramsWithPipeline); err != nil { @@ -114,7 +117,7 @@ func TestValidateParamsDisabled(t *testing.T) { Name: bundle.ParamBundle, Value: *pipelinev1.NewStructuredValues("bar"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} err = resolver.ValidateParams(resolverDisabledContext(), params) @@ -139,7 +142,7 @@ func TestValidateParamsMissing(t *testing.T) { Name: bundle.ParamName, Value: *pipelinev1.NewStructuredValues("foo"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} err = resolver.ValidateParams(context.Background(), paramsMissingBundle) @@ -154,7 +157,7 @@ func TestValidateParamsMissing(t *testing.T) { Name: bundle.ParamBundle, Value: *pipelinev1.NewStructuredValues("bar"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} err = resolver.ValidateParams(context.Background(), paramsMissingName) @@ -178,7 +181,7 @@ func TestResolveDisabled(t *testing.T) { Name: bundle.ParamBundle, Value: *pipelinev1.NewStructuredValues("bar"), }, { - Name: bundle.ParamServiceAccount, + Name: bundle.ParamImagePullSecret, Value: *pipelinev1.NewStructuredValues("baz"), }} _, err = resolver.Resolve(resolverDisabledContext(), params) @@ -191,11 +194,56 @@ func TestResolveDisabled(t *testing.T) { } } +func TestResolve_KeyChainError(t *testing.T) { + resolver := &bundle.Resolver{} + params := ¶ms{ + bundle: "foo", + name: "example-task", + kind: "task", + secret: "bar", + } + + ctx, _ := ttesting.SetupFakeContext(t) + request := createRequest(params) + + d := test.Data{ + ResolutionRequests: []*v1beta1.ResolutionRequest{request}, + ConfigMaps: []*corev1.ConfigMap{{ + ObjectMeta: metav1.ObjectMeta{ + Name: bundle.ConfigMapName, + Namespace: resolverconfig.ResolversNamespace(system.Namespace()), + }, + Data: map[string]string{ + bundle.ConfigKind: "task", + bundle.ConfigSecret: "placeholder", + }, + }}, + } + + testAssets, cancel := frtesting.GetResolverFrameworkController(ctx, t, d, resolver) + defer cancel() + + expectedErr := apierrors.NewBadRequest("bad request") + // return error when getting secrets from kube client + testAssets.Clients.Kube.Fake.PrependReactor("get", "secrets", func(action ktesting.Action) (bool, runtime.Object, error) { + return true, nil, expectedErr + }) + + err := testAssets.Controller.Reconciler.Reconcile(testAssets.Ctx, strings.Join([]string{request.Namespace, request.Name}, "/")) + if err == nil { + t.Fatalf("expected to get error but got nothing") + } + + if !errors.Is(err, expectedErr) { + t.Fatalf("expected to get error %v, but got %v", expectedErr, err) + } +} + type params struct { - serviceAccount string - bundle string - name string - kind string + secret string + bundle string + name string + kind string } func TestResolve(t *testing.T) { @@ -397,9 +445,9 @@ func TestResolve(t *testing.T) { resolver := &bundle.Resolver{} confMap := map[string]string{ bundle.ConfigKind: "task", - // service account is not used in testing, but we have to set this since - // param validation will check if the service account is set either from param or from configmap. - bundle.ConfigServiceAccount: "placeholder", + // secret is not used in testing, but we have to set this since + // param validation will check if it is set either from param or from configmap. + bundle.ConfigSecret: "placeholder", } for _, tc := range testcases { @@ -491,8 +539,8 @@ func createRequest(p *params) *v1beta1.ResolutionRequest { Name: bundle.ParamKind, Value: *pipelinev1.NewStructuredValues(p.kind), }, { - Name: bundle.ParamServiceAccount, - Value: *pipelinev1.NewStructuredValues(p.serviceAccount), + Name: bundle.ParamImagePullSecret, + Value: *pipelinev1.NewStructuredValues(p.secret), }}, }, }