Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TEP-0089] Inject SpireControllerAPIClient into the Taskrun controller and reconciler. #6627

Merged
merged 1 commit into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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{}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: why do we need to implement OnStore? Are we supporting changing the SPIRE client without a controller restart if the config changes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The configStore reads in the config and stores it into its local structures. Spire controller maintains its own local config. This does not get updated with the changes in the actual configMap. Essentially the Spire ConfigMap does not make it to the Spire Controller without this callback.

One way to get around this without the callback could be to load from the ConfigStore into the SpireCntroller at the beginning of the reconciler as done for other configs whcih get copied into the. context.

which will result in something like this.
// If configStore is set, attach the frozen configuration to the context.
if r.configStore != nil {
ctx = r.configStore.ToContext(ctx)
r.SpireClient.SetConfig(ctx)
}

WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see...I think the current impl is fine

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)
jerop marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

// 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