Skip to content

Commit

Permalink
[TEP-0089] SPIRE for non-falsifiable provenance.
Browse files Browse the repository at this point in the history
Inject SpireControllerAPIClient into the controller and the taskrun reconciler.

This commit is part of a series of PRs to implement TEP-0089.
The implementation of TEP-0089 is tracked in the issue [tektoncd#6597](tektoncd#6597).
  • Loading branch information
jagathprakash committed May 16, 2023
1 parent add97ea commit 810803d
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 2 deletions.
5 changes: 4 additions & 1 deletion pkg/reconciler/taskrun/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
cloudeventclient "github.com/tektoncd/pipeline/pkg/reconciler/events/cloudevent"
"github.com/tektoncd/pipeline/pkg/reconciler/volumeclaim"
resolution "github.com/tektoncd/pipeline/pkg/resolution/resource"
"github.com/tektoncd/pipeline/pkg/spire"
"github.com/tektoncd/pipeline/pkg/taskrunmetrics"
"go.opentelemetry.io/otel/trace"
"k8s.io/client-go/tools/cache"
Expand All @@ -55,7 +56,8 @@ func NewController(opts *pipeline.Options, clock clock.PassiveClock, tracerProvi
limitrangeInformer := limitrangeinformer.Get(ctx)
verificationpolicyInformer := verificationpolicyinformer.Get(ctx)
resolutionInformer := resolutioninformer.Get(ctx)
configStore := config.NewStore(logger.Named("config-store"), taskrunmetrics.MetricsOnStore(logger))
spireClient := spire.GetControllerAPIClient(ctx)
configStore := config.NewStore(logger.Named("config-store"), taskrunmetrics.MetricsOnStore(logger), spire.OnStore(ctx, logger))
configStore.WatchConfigs(cmw)

entrypointCache, err := pod.NewEntrypointCache(kubeclientset)
Expand All @@ -68,6 +70,7 @@ func NewController(opts *pipeline.Options, clock clock.PassiveClock, tracerProvi
PipelineClientSet: pipelineclientset,
Images: opts.Images,
Clock: clock,
spireClient: spireClient,
taskRunLister: taskRunInformer.Lister(),
limitrangeLister: limitrangeInformer.Lister(),
verificationPolicyLister: verificationpolicyInformer.Lister(),
Expand Down
2 changes: 2 additions & 0 deletions pkg/reconciler/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/tektoncd/pipeline/pkg/reconciler/volumeclaim"
"github.com/tektoncd/pipeline/pkg/remote"
resolution "github.com/tektoncd/pipeline/pkg/resolution/resource"
"github.com/tektoncd/pipeline/pkg/spire"
"github.com/tektoncd/pipeline/pkg/taskrunmetrics"
_ "github.com/tektoncd/pipeline/pkg/taskrunmetrics/fake" // Make sure the taskrunmetrics are setup
"github.com/tektoncd/pipeline/pkg/trustedresources"
Expand Down Expand Up @@ -78,6 +79,7 @@ type Reconciler struct {
Clock clock.PassiveClock

// listers index properties about resources
spireClient spire.ControllerAPIClient
taskRunLister listers.TaskRunLister
limitrangeLister corev1Listers.LimitRangeLister
podLister corev1Listers.PodLister
Expand Down
26 changes: 25 additions & 1 deletion pkg/spire/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import (
"github.com/spiffe/go-spiffe/v2/workloadapi"
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
spiffetypes "github.com/spiffe/spire-api-sdk/proto/spire/api/types"
"github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
spireconfig "github.com/tektoncd/pipeline/pkg/spire/config"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
Expand All @@ -45,14 +47,30 @@ func init() {
// controllerKey is a way to associate the ControllerAPIClient from inside the context.Context
type controllerKey struct{}

// OnStore stores the changed spire config into the SpireClientApi
func OnStore(ctx context.Context, logger *zap.SugaredLogger) func(name string, value interface{}) {
return func(name string, value interface{}) {
if name == config.GetSpireConfigName() {
cfg, ok := value.(*spireconfig.SpireConfig)
if !ok {
logger.Error("Failed to do type assertion for extracting SPIRE config")
return
}
controllerAPIClient := GetControllerAPIClient(ctx)
controllerAPIClient.Close()
controllerAPIClient.SetConfig(*cfg)
}
}
}

// GetControllerAPIClient extracts the ControllerAPIClient from the context.
func GetControllerAPIClient(ctx context.Context) ControllerAPIClient {
untyped := ctx.Value(controllerKey{})
if untyped == nil {
logging.FromContext(ctx).Errorf("Unable to fetch client from context.")
return nil
}
return untyped.(*spireControllerAPIClient)
return untyped.(ControllerAPIClient)
}

func withControllerClient(ctx context.Context, cfg *rest.Config) context.Context {
Expand All @@ -67,6 +85,8 @@ type spireControllerAPIClient struct {
workloadAPI *workloadapi.Client
}

var _ ControllerAPIClient = (*spireControllerAPIClient)(nil)

func (sc *spireControllerAPIClient) setupClient(ctx context.Context) error {
if sc.config == nil {
return errors.New("config has not been set yet")
Expand Down Expand Up @@ -297,18 +317,22 @@ func (sc *spireControllerAPIClient) Close() error {
if err != nil {
return err
}
sc.serverConn = nil
}
if sc.workloadAPI != nil {
err = sc.workloadAPI.Close()
if err != nil {
return err
}
sc.workloadAPI = nil
}
if sc.workloadConn != nil {
err = sc.workloadConn.Close()
if err != nil {
return err
}
sc.workloadConn = nil
}
sc.entryClient = nil
return nil
}
3 changes: 3 additions & 0 deletions pkg/spire/spire_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type MockClient struct {
SignOverride func(ctx context.Context, results []result.RunResult) ([]result.RunResult, error)
}

var _ ControllerAPIClient = (*MockClient)(nil)
var _ EntrypointerAPIClient = (*MockClient)(nil)

const controllerSvid = "CONTROLLER_SVID_DATA"

func (*MockClient) mockSign(content, signedBy string) string {
Expand Down
27 changes: 27 additions & 0 deletions pkg/spire/spire_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ import (
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/svid/x509svid"
pconf "github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
ttesting "github.com/tektoncd/pipeline/pkg/reconciler/testing"
"github.com/tektoncd/pipeline/pkg/result"
"github.com/tektoncd/pipeline/pkg/spire/config"
"github.com/tektoncd/pipeline/pkg/spire/test"
"github.com/tektoncd/pipeline/pkg/spire/test/fakeworkloadapi"
"github.com/tektoncd/pipeline/test/diff"
corev1 "k8s.io/api/core/v1"
"knative.dev/pkg/logging"
)
Expand Down Expand Up @@ -666,6 +669,30 @@ func TestTaskRunResultsSignTamper(t *testing.T) {
}
}

func TestOnStore(t *testing.T) {
ctx, _ := ttesting.SetupDefaultContext(t)
logger := logging.FromContext(ctx)
ctx = context.WithValue(ctx, controllerKey{}, &spireControllerAPIClient{
config: &config.SpireConfig{
TrustDomain: "before_test_domain",
SocketPath: "before_test_socket_path",
ServerAddr: "before_test_server_path",
NodeAliasPrefix: "before_test_node_alias_prefix",
},
})
want := config.SpireConfig{
TrustDomain: "after_test_domain",
SocketPath: "after_test_socket_path",
ServerAddr: "after_test_server_path",
NodeAliasPrefix: "after_test_node_alias_prefix",
}
OnStore(ctx, logger)(pconf.GetSpireConfigName(), &want)
got := *GetControllerAPIClient(ctx).(*spireControllerAPIClient).config
if d := cmp.Diff(want, got); d != "" {
t.Fatalf("Diff in TestOnStore, diff: %s", diff.PrintWantGot(d))
}
}

func x509svids(ca *test.CA, ids ...spiffeid.ID) []*x509svid.SVID {
svids := []*x509svid.SVID{}
for _, id := range ids {
Expand Down

0 comments on commit 810803d

Please sign in to comment.