Skip to content

Commit

Permalink
Merge pull request #13 from JoshVanL/csi-driver-write-files-go-spiffe…
Browse files Browse the repository at this point in the history
…-compatable

Make CSI driver spiffe writeFiles compatable with go-spiffe `x509svid.Parse`
  • Loading branch information
jetstack-bot authored May 4, 2022
2 parents e1fd00c + 77239bf commit e804a9f
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 76 deletions.
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/onsi/gomega v1.19.0
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spiffe/go-spiffe/v2 v2.1.0
github.com/stretchr/testify v1.7.1
gopkg.in/square/go-jose.v2 v2.6.0
k8s.io/api v0.23.6
Expand Down Expand Up @@ -128,6 +129,7 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
github.com/zeebo/errs v1.2.2 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
Expand All @@ -141,8 +143,8 @@ require (
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 // indirect
google.golang.org/grpc v1.43.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
google.golang.org/grpc v1.46.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/gorp.v1 v1.7.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
Expand Down
17 changes: 14 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
Expand Down Expand Up @@ -416,6 +417,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
Expand Down Expand Up @@ -1055,6 +1057,8 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spiffe/go-spiffe/v2 v2.1.0 h1:IZRlWhyFpPbJOiK8K+MwEFPU/QCdaW4Zf5bmIKBd3XM=
github.com/spiffe/go-spiffe/v2 v2.1.0/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down Expand Up @@ -1116,6 +1120,8 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMzt
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
Expand Down Expand Up @@ -1618,6 +1624,7 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
Expand Down Expand Up @@ -1690,9 +1697,11 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand All @@ -1705,8 +1714,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand All @@ -1731,6 +1741,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
Expand Down
154 changes: 99 additions & 55 deletions internal/csi/driver/camanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,111 +21,155 @@ import (
"context"
"fmt"
"time"

"github.com/cert-manager/csi-driver-spiffe/internal/csi/rootca"
"github.com/cert-manager/csi-lib/storage"
"github.com/go-logr/logr"
)

// manageCAFiles subscribes to events from the Root CAs provider, and updates
// all managed volumes CA files accordingly. Exits early if rootCAs is not
// configured.
func (d *Driver) manageCAFiles(ctx context.Context, updateRetryPeriod time.Duration) {
log := d.log.WithName("ca-manager")
// camanager is a process responsible for distributing trust bundles to
// mounting pods.
type camanager struct {
// log is the logger for camanager.
log logr.Logger

// store is the csi-lib file system storage implementation. Must by file
// system in order to read volumes back from mounted pods.
store *storage.Filesystem

// rootCAs exposes the current trust bundle to be propagated, and signals
// when a new trust bundle is available.
rootCAs rootca.Interface

// certFileName, keyFileName, caFileName are the names used when writing file
// to volumes.
certFileName, keyFileName, caFileName string

// updateRootCAFiles is a func to update all managed volumes with the current
// root CA certificates PEM. Used for testing.
updateRootCAFilesFn func() error
}

// newCAManager constructs a new camanager which distributes new trust bundles
// to mounted pods, as they are changed.
func newCAManager(log logr.Logger,
store *storage.Filesystem,
rootCAs rootca.Interface,
certFileName, keyFileName, caFileName string,
) *camanager {
c := &camanager{
log: log.WithName("ca-manager"),
store: store,
rootCAs: rootCAs,
certFileName: certFileName,
keyFileName: keyFileName,
caFileName: caFileName,
}
c.updateRootCAFilesFn = c.updateRootCAFiles
return c
}

// run subscribes to events from the Root CAs provider, and updates all managed
// volumes CA files accordingly. Exits early if rootCAs is not configured.
// Blocking function.
func (c *camanager) run(ctx context.Context, updateRetryPeriod time.Duration) {
// Exit straight away if root CAs haven't been configured.
if d.rootCAs == nil {
log.Info("not running CA file manager, root CA certificates not configured")
if c.rootCAs == nil {
c.log.Info("not running CA file manager, root CA certificates not configured")
return
}

watcher := d.rootCAs.Subscribe()
watcher := c.rootCAs.Subscribe()

log.Info("starting root CA file manager")
c.log.Info("starting root CA file manager")

// updateChan is used to trigger an update of CA certificates of file of all
// managed volumes. Trigged by both RootCAs events, as well as retrying updates on errors.
updateChan := make(chan struct{}, 1)

go func() {
for {
select {
case <-ctx.Done():
log.Info("closing root CA file manager")
return

case <-watcher:
updateChan <- struct{}{}

case <-updateChan:
log.Info("root CA file event received, updating managed volumes")

if err := d.updateRootCAFilesFn(); err != nil {
log.Error(err, "failed to update root CA files on managed volumes")

// Retry updating the root CA files.
go func() {
select {
// Wait for 5 seconds before retrying.
case <-time.After(updateRetryPeriod):
case <-ctx.Done():
return
}
log.Error(err, "retrying CA file update...")
updateChan <- struct{}{}
}()

continue
}

log.Info("updated root CA files on managed volumes")
for {
select {
case <-ctx.Done():
c.log.Info("closing root CA file manager")
return

case <-watcher:
updateChan <- struct{}{}

case <-updateChan:
c.log.Info("root CA file event received, updating managed volumes")

if err := c.updateRootCAFilesFn(); err != nil {
c.log.Error(err, "failed to update root CA files on managed volumes")

// Retry updating the root CA files.
go func() {
select {
// Wait for 5 seconds before retrying.
case <-time.After(updateRetryPeriod):
case <-ctx.Done():
return
}
c.log.Error(err, "retrying CA file update...")
updateChan <- struct{}{}
}()

continue
}

c.log.Info("updated root CA files on managed volumes")
}
}()
}
}

// updateRootCAFiles will update all managed volumes with the CA certificates
// data returned from rootCAs.
func (d *Driver) updateRootCAFiles() error {
if d.rootCAs == nil {
func (c *camanager) updateRootCAFiles() error {
if c.rootCAs == nil {
// Exit early if rootCAs is not configured.
return nil
}

volumeIDs, err := d.store.ListVolumes()
log := c.log.WithName("ca-updater")

volumeIDs, err := c.store.ListVolumes()
if err != nil {
return fmt.Errorf("failed to list managed volumes: %w", err)
}

for _, volumeID := range volumeIDs {
meta, err := d.store.ReadMetadata(volumeID)
meta, err := c.store.ReadMetadata(volumeID)
if err != nil {
return fmt.Errorf("%q: failed to read metadata from volume: %w", volumeID, err)
}

certData, err := d.store.ReadFile(volumeID, d.certFileName)
certData, err := c.store.ReadFile(volumeID, c.certFileName)
if err != nil {
return fmt.Errorf("%q: failed to read certificate file from volume to perform write: %w",
volumeID, err)
}
keyData, err := d.store.ReadFile(volumeID, d.keyFileName)
keyData, err := c.store.ReadFile(volumeID, c.keyFileName)
if err != nil {
return fmt.Errorf("%q: failed to read key file from volume to perform write: %w",
volumeID, err)
}

// No need to re-write CA data again if it hasn't changed on file.
caData, err := d.store.ReadFile(volumeID, d.caFileName)
if err == nil && bytes.Equal(caData, d.rootCAs.CertificatesPEM()) {
caData, err := c.store.ReadFile(volumeID, c.caFileName)
if err == nil && bytes.Equal(caData, c.rootCAs.CertificatesPEM()) {
continue
}

if err := d.store.WriteFiles(meta, map[string][]byte{
d.certFileName: certData,
d.keyFileName: keyData,
d.caFileName: d.rootCAs.CertificatesPEM(),
if err := c.store.WriteFiles(meta, map[string][]byte{
c.certFileName: certData,
c.keyFileName: keyData,
c.caFileName: c.rootCAs.CertificatesPEM(),
}); err != nil {
return fmt.Errorf("%q: failed to write new ca data to volume: %w",
volumeID, err)
}

d.log.WithName("ca-updater").Info("updated CA file on volume", "volume", volumeID)
log.Info("updated CA file on volume", "volume", volumeID)
}

return nil
Expand Down
10 changes: 6 additions & 4 deletions internal/csi/driver/camanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ func Test_manageCAFiles(t *testing.T) {

t.Log("starting manageCAFiles()")
rootCAsChan := make(chan []byte)
d := &Driver{
c := &camanager{
log: klogr.New(),
rootCAs: rootca.NewMemory(ctx, rootCAsChan),
}
d.manageCAFiles(ctx, time.Millisecond*5)
go func() {
c.run(ctx, time.Millisecond*5)
}()

t.Log("if root CAs update happens, expect updateRootCAFilesFn() to be called")
calledCtx, calledCancel := context.WithCancel(context.TODO())
d.updateRootCAFilesFn = func() error {
c.updateRootCAFilesFn = func() error {
t.Log("updateRootCAFilesFn() called")
calledCancel()
return nil
Expand All @@ -63,7 +65,7 @@ func Test_manageCAFiles(t *testing.T) {
t.Log("should call updateRootCAFilesFn() again if it fails")
var i int
calledTwiceChan := make(chan struct{})
d.updateRootCAFilesFn = func() error {
c.updateRootCAFilesFn = func() error {
if i == 0 {
i++
t.Log("returning error from updateRootCAFilesFn()")
Expand Down
Loading

0 comments on commit e804a9f

Please sign in to comment.