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

Agentless POC #1

Closed
wants to merge 5 commits into from
Closed
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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ serviceprotos := \
proto/private/test/catalogtest/test.proto \
proto/spire/agent/keymanager/keymanager.proto \
proto/spire/agent/nodeattestor/nodeattestor.proto \
proto/spire/agent/svidstore/svidstore.proto \
proto/spire/agent/workloadattestor/workloadattestor.proto \
proto/spire/api/node/node.proto \
proto/spire/api/registration/registration.proto \
Expand Down Expand Up @@ -187,6 +188,7 @@ plugingen_plugins = \
proto/spire/server/keymanager/keymanager.proto,pkg/server/plugin/keymanager,KeyManager \
proto/spire/agent/nodeattestor/nodeattestor.proto,pkg/agent/plugin/nodeattestor,NodeAttestor \
proto/spire/agent/workloadattestor/workloadattestor.proto,pkg/agent/plugin/workloadattestor,WorkloadAttestor \
proto/spire/agent/svidstore/svidstore.proto,pkg/agent/plugin/svidstore,SVIDStore \
proto/spire/agent/keymanager/keymanager.proto,pkg/agent/plugin/keymanager,KeyManager \
proto/private/test/catalogtest/test.proto,proto/private/test/catalogtest,Plugin,shared \

Expand Down
27 changes: 27 additions & 0 deletions conf/agent/agent_full.conf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,33 @@ plugins {
}
}

# SVIDStore "aws_secretsmanager": An SVID store that stores the SVIDs in
# AWS Secrets Manager.
# SVIDStore "aws_secretsmanager" {
# plugin_data {
# # access_key_id: AWS access key id. Default: value of
# # AWS_ACCESS_KEY_ID environment variable.
# # access_key_id = ""

# # secret_access_key: AWS secret access key. Default: value of
# # AWS_SECRET_ACCESS_KEY environment variable.
# # secret_access_key = ""

# # regions: AWS regions to store the secrets.
# # regions = []
# }
# }

# SVIDStore "gcloud_secretsmanager": An SVID store that stores the SVIDs in
# GCloud Secrets Manager.
# SVIDStore "gcloud_secretsmanager" {
# plugin_data {
# # service_account_file: Path to the service account file used to
# # authenticate with the Google Compute Engine API.
# # service_account_file = ""
# }
# }

# WorkloadAttestor "docker": A workload attestor which allows selectors
# based on docker constructs such label and image_id.
WorkloadAttestor "docker" {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.15
replace github.com/spiffe/spire/proto/spire => ./proto/spire

require (
cloud.google.com/go v0.56.0
cloud.google.com/go/storage v1.6.0
github.com/Azure/azure-sdk-for-go v44.0.0+incompatible
github.com/Azure/go-autorest/autorest v0.11.0
Expand Down
35 changes: 33 additions & 2 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path"
"runtime"
"strings"
"sync"
"time"

Expand All @@ -18,6 +19,9 @@ import (
"github.com/spiffe/spire/pkg/agent/catalog"
"github.com/spiffe/spire/pkg/agent/endpoints"
"github.com/spiffe/spire/pkg/agent/manager"
"github.com/spiffe/spire/pkg/agent/manager/pipe"
"github.com/spiffe/spire/pkg/agent/plugin/svidstore"
"github.com/spiffe/spire/pkg/agent/svid/store"
common_catalog "github.com/spiffe/spire/pkg/common/catalog"
"github.com/spiffe/spire/pkg/common/health"
"github.com/spiffe/spire/pkg/common/hostservices/metricsservice"
Expand Down Expand Up @@ -90,7 +94,17 @@ func (a *Agent) Run(ctx context.Context) error {
return err
}

manager, err := a.newManager(ctx, cat, metrics, as)
// If there is an SVID Store plugin, create a buffered pipe
var pipeIn pipe.In
var pipeOut pipe.Out

hasStores := len(cat.GetSVIDStores()) > 0
if hasStores {
pipeIn, pipeOut = pipe.BufferedPipe(1000)

Choose a reason for hiding this comment

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

should buffer size be an agent config? I could see operators having a wide range of typical count of secret store SVIDs they would anticipate handling. Some may be doing SVID Store pushes all day and want channels to be blocked as infrequently as possible, others (as a lesser concern given SVID size) may have very few cases and so not need the additional memory allocation.

defer pipeIn.Close()
}

manager, err := a.newManager(ctx, cat, metrics, as, pipeIn)
if err != nil {
return err
}
Expand All @@ -116,6 +130,12 @@ func (a *Agent) Run(ctx context.Context) error {
tasks = append(tasks, adminEndpoints.ListenAndServe)
}

// If an SVID store is configured, create store and add it to tasks
if hasStores {
store := a.newStore(cat, pipeOut)
tasks = append(tasks, store.Run)
}

err = util.RunTasks(ctx, tasks...)
if err == context.Canceled {
err = nil
Expand Down Expand Up @@ -197,7 +217,7 @@ func (a *Agent) attest(ctx context.Context, cat catalog.Catalog, metrics telemet
return node_attestor.New(&config).Attest(ctx)
}

func (a *Agent) newManager(ctx context.Context, cat catalog.Catalog, metrics telemetry.Metrics, as *node_attestor.AttestationResult) (manager.Manager, error) {
func (a *Agent) newManager(ctx context.Context, cat catalog.Catalog, metrics telemetry.Metrics, as *node_attestor.AttestationResult, pipeIn pipe.In) (manager.Manager, error) {
config := &manager.Config{
SVID: as.SVID,
SVIDKey: as.Key,
Expand All @@ -210,6 +230,7 @@ func (a *Agent) newManager(ctx context.Context, cat catalog.Catalog, metrics tel
BundleCachePath: a.bundleCachePath(),
SVIDCachePath: a.agentSVIDPath(),
SyncInterval: a.c.SyncInterval,
PipeIn: pipeIn,
}

mgr := manager.New(config)
Expand All @@ -220,6 +241,16 @@ func (a *Agent) newManager(ctx context.Context, cat catalog.Catalog, metrics tel
return mgr, nil
}

func (a *Agent) newStore(c catalog.Catalog, pipeOut pipe.Out) store.Service {
config := store.Config{
Catalog: c,
Log: a.c.Log.WithField(telemetry.SubsystemName, strings.ToLower(svidstore.Type)),
PipeOut: pipeOut,
}

return store.New(config)
}

func (a *Agent) newEndpoints(cat catalog.Catalog, metrics telemetry.Metrics, mgr manager.Manager) endpoints.Server {
return endpoints.New(endpoints.Config{
BindAddr: a.c.BindAddress,
Expand Down
17 changes: 17 additions & 0 deletions pkg/agent/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
na_k8s_sat "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/k8s/sat"
na_sshpop "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/sshpop"
na_x509pop "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/x509pop"
"github.com/spiffe/spire/pkg/agent/plugin/svidstore"
ss_aws "github.com/spiffe/spire/pkg/agent/plugin/svidstore/aws"
ss_gcloud "github.com/spiffe/spire/pkg/agent/plugin/svidstore/gcloud"
"github.com/spiffe/spire/pkg/agent/plugin/workloadattestor"
wa_docker "github.com/spiffe/spire/pkg/agent/plugin/workloadattestor/docker"
wa_k8s "github.com/spiffe/spire/pkg/agent/plugin/workloadattestor/k8s"
Expand All @@ -29,6 +32,7 @@ type Catalog interface {
GetKeyManager() KeyManager
GetNodeAttestor() NodeAttestor
GetWorkloadAttestors() []WorkloadAttestor
GetSVIDStores() []SVIDStores
}

type GlobalConfig = catalog.GlobalConfig
Expand All @@ -39,6 +43,7 @@ func KnownPlugins() []catalog.PluginClient {
return []catalog.PluginClient{
keymanager.PluginClient,
nodeattestor.PluginClient,
svidstore.PluginClient,
workloadattestor.PluginClient,
}
}
Expand All @@ -59,6 +64,8 @@ func BuiltIns() []catalog.Plugin {
na_azure_msi.BuiltIn(),
na_k8s_sat.BuiltIn(),
na_k8s_psat.BuiltIn(),
ss_aws.BuiltIn(),
ss_gcloud.BuiltIn(),
wa_k8s.BuiltIn(),
wa_unix.BuiltIn(),
wa_docker.BuiltIn(),
Expand All @@ -74,6 +81,11 @@ type NodeAttestor struct {
nodeattestor.NodeAttestor
}

type SVIDStores struct {
catalog.PluginInfo
svidstore.SVIDStore
}

type WorkloadAttestor struct {
catalog.PluginInfo
workloadattestor.WorkloadAttestor
Expand All @@ -82,6 +94,7 @@ type WorkloadAttestor struct {
type Plugins struct {
KeyManager KeyManager
NodeAttestor NodeAttestor
SVIDStores []SVIDStores
WorkloadAttestors []WorkloadAttestor `catalog:"min=1"`
}

Expand All @@ -95,6 +108,10 @@ func (p *Plugins) GetNodeAttestor() NodeAttestor {
return p.NodeAttestor
}

func (p *Plugins) GetSVIDStores() []SVIDStores {
return p.SVIDStores
}

func (p *Plugins) GetWorkloadAttestors() []WorkloadAttestor {
return p.WorkloadAttestors
}
Expand Down
32 changes: 31 additions & 1 deletion pkg/agent/manager/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/sirupsen/logrus"
"github.com/spiffe/spire/pkg/agent/manager/pipe"
"github.com/spiffe/spire/pkg/common/bundleutil"
"github.com/spiffe/spire/pkg/common/telemetry"
"github.com/spiffe/spire/proto/spire/common"
Expand Down Expand Up @@ -114,6 +115,9 @@ type Cache struct {

// bundles holds the trust bundles, keyed by trust domain id (i.e. "spiffe://domain.test")
bundles map[string]*bundleutil.Bundle

// buffered pipe for 'storable' SVIDs
pipeIn pipe.In
}

// StaleEntry holds stale entries with SVIDs expiration time
Expand All @@ -124,7 +128,7 @@ type StaleEntry struct {
ExpiresAt time.Time
}

func New(log logrus.FieldLogger, trustDomainID string, bundle *Bundle, metrics telemetry.Metrics) *Cache {
func New(log logrus.FieldLogger, trustDomainID string, bundle *Bundle, metrics telemetry.Metrics, pipeIn pipe.In) *Cache {
return &Cache{
BundleCache: NewBundleCache(trustDomainID, bundle),
JWTSVIDCache: NewJWTSVIDCache(),
Expand All @@ -138,6 +142,7 @@ func New(log logrus.FieldLogger, trustDomainID string, bundle *Bundle, metrics t
bundles: map[string]*bundleutil.Bundle{
trustDomainID: bundle,
},
pipeIn: pipeIn,
}
}

Expand Down Expand Up @@ -393,6 +398,31 @@ func (c *Cache) UpdateSVIDs(update *UpdateSVIDs) {
})
log.Debug("SVID updated")

// Verify if pipe exists and if current entry is storable
if c.pipeIn != nil && c.pipeIn.IsStorable(record.entry.Selectors) {
update := &pipe.SVIDUpdate{
Entry: record.entry,
SVID: record.svid.Chain,
PrivateKey: record.svid.PrivateKey,
Bundle: c.bundles[c.trustDomainID],
FederatedBundles: make(map[string]*bundleutil.Bundle),
}

for _, federatesWith := range record.entry.FederatesWith {
if federatedBundle := c.bundles[federatesWith]; federatedBundle != nil {
update.FederatedBundles[federatesWith] = federatedBundle
} else {
c.log.WithFields(logrus.Fields{
telemetry.RegistrationID: record.entry.EntryId,
telemetry.SPIFFEID: record.entry.SpiffeId,
telemetry.FederatedBundle: federatesWith,
}).Warn("Federated bundle contents missing")
}
}

c.pipeIn.Push(update)
}

// Registration entry is updated, remove it from stale map
delete(c.staleEntries, entryID)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/manager/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func TestSubcriberNotificationsOnSelectorChanges(t *testing.T) {

func newTestCache() *Cache {
log, _ := test.NewNullLogger()
return New(log, "spiffe://domain.test", bundleV1, telemetry.Blackhole{})
return New(log, "spiffe://domain.test", bundleV1, telemetry.Blackhole{}, nil)
}

func TestSubcriberNotifiedWhenEntryDropped(t *testing.T) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/agent/manager/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spiffe/spire/pkg/agent/catalog"
"github.com/spiffe/spire/pkg/agent/manager/cache"
"github.com/spiffe/spire/pkg/agent/manager/pipe"
"github.com/spiffe/spire/pkg/agent/svid"
"github.com/spiffe/spire/pkg/common/telemetry"
)
Expand All @@ -33,6 +34,9 @@ type Config struct {

// Clk is the clock the manager will use to get time
Clk clock.Clock

// Buffered pipe used to push all 'storable' SVIDs
PipeIn pipe.In
}

// New creates a cache manager based on c's configuration
Expand All @@ -53,7 +57,7 @@ func newManager(c *Config) *manager {
c.Clk = clock.New()
}

cache := cache.New(c.Log.WithField(telemetry.SubsystemName, telemetry.CacheManager), c.TrustDomain.String(), c.Bundle, c.Metrics)
cache := cache.New(c.Log.WithField(telemetry.SubsystemName, telemetry.CacheManager), c.TrustDomain.String(), c.Bundle, c.Metrics, c.PipeIn)

rotCfg := &svid.RotatorConfig{
Catalog: c.Catalog,
Expand Down
Loading