Skip to content
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
29 changes: 18 additions & 11 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,26 @@ type Plugin struct {
}

type NodeStore interface {
Attest(ctx context.Context, ek *attest.EK) error
Attest(ctx context.Context, ek *attest.EK) (NodeMeta, error)
Configure(string) (*Config, error)
Validate(string) error
}

// NodeMeta defines metadata about a node in a node store.
type NodeMeta struct {
// SelectorValues is a slice of additional node selector values to use for the node.
SelectorValues []string
}

type FileNodeStore struct {
caPath string
hashPath string
}

func (s *FileNodeStore) Attest(ctx context.Context, ek *attest.EK) error {
func (s *FileNodeStore) Attest(ctx context.Context, ek *attest.EK) (NodeMeta, error) {
hashEncoded, err := common.GetPubHash(ek)
if err != nil {
return status.Errorf(codes.InvalidArgument, "tpm: could not get public key hash: %v", err)
return NodeMeta{}, status.Errorf(codes.InvalidArgument, "tpm: could not get public key hash: %v", err)
}

validEK := false
Expand All @@ -114,7 +120,7 @@ func (s *FileNodeStore) Attest(ctx context.Context, ek *attest.EK) error {
if !validEK && s.caPath != "" && ek.Certificate != nil {
files, err := os.ReadDir(s.caPath)
if err != nil {
return status.Errorf(codes.InvalidArgument, "tpm: could not open ca directory: %v", err)
return NodeMeta{}, status.Errorf(codes.InvalidArgument, "tpm: could not open ca directory: %v", err)
}

roots := x509.NewCertPool()
Expand All @@ -123,7 +129,7 @@ func (s *FileNodeStore) Attest(ctx context.Context, ek *attest.EK) error {
filename := filepath.Join(s.caPath, file.Name())
certData, err := os.ReadFile(filename)
if err != nil {
return status.Errorf(codes.InvalidArgument, "tpm: could not read cert data for '%s': %v", filename, err)
return NodeMeta{}, status.Errorf(codes.InvalidArgument, "tpm: could not read cert data for '%s': %v", filename, err)
}

ok := roots.AppendCertsFromPEM(certData)
Expand All @@ -137,22 +143,22 @@ func (s *FileNodeStore) Attest(ctx context.Context, ek *attest.EK) error {
continue
}

return status.Errorf(codes.InvalidArgument, "tpm: could not parse cert data for '%s': %v", filename, err)
return NodeMeta{}, status.Errorf(codes.InvalidArgument, "tpm: could not parse cert data for '%s': %v", filename, err)
}
}

opts := x509.VerifyOptions{Roots: roots}
if _, err = ek.Certificate.Verify(opts); err != nil {
return fmt.Errorf("tpm: could not verify cert: %v", err)
return NodeMeta{}, fmt.Errorf("tpm: could not verify cert: %v", err)
}
validEK = true
}

if !validEK {
return fmt.Errorf("tpm: could not validate EK")
return NodeMeta{}, fmt.Errorf("tpm: could not validate EK")
}

return nil
return NodeMeta{}, nil
}

func (s *FileNodeStore) Configure(hclCfg string) (*Config, error) {
Expand Down Expand Up @@ -249,7 +255,8 @@ func (p *Plugin) Attest(stream nodeattestorv1.NodeAttestor_AttestServer) error {
return err
}

if err := p.ns.Attest(stream.Context(), ek); err != nil {
nodeMeta, err := p.ns.Attest(stream.Context(), ek)
if err != nil {
return err
}

Expand Down Expand Up @@ -304,7 +311,7 @@ func (p *Plugin) Attest(stream nodeattestorv1.NodeAttestor_AttestServer) error {
Response: &nodeattestorv1.AttestResponse_AgentAttributes{
AgentAttributes: &nodeattestorv1.AgentAttributes{
SpiffeId: common.AgentID(p.config.trustDomain, hashEncoded),
SelectorValues: buildSelectors(hashEncoded),
SelectorValues: append(buildSelectors(hashEncoded), nodeMeta.SelectorValues...),
CanReattest: true,
},
},
Expand Down
8 changes: 5 additions & 3 deletions pkg/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestNodeStore_Attest_Success(t *testing.T) {
hashEncoded, err := common.GetPubHash(ekWrapper)
require.NoError(t, err)

err = os.WriteFile(filepath.Join(tmpDir, hashEncoded), []byte{}, 0644)
err = os.WriteFile(filepath.Join(tmpDir, hashEncoded), []byte{}, 0o644)
require.NoError(t, err)

config := &Config{
Expand All @@ -33,8 +33,9 @@ func TestNodeStore_Attest_Success(t *testing.T) {
}
p := NewFromConfig(config)

err = p.ns.Attest(context.Background(), ekWrapper)
nodeMeta, err := p.ns.Attest(context.Background(), ekWrapper)
assert.NoError(t, err, "NodeStore should validate the EK against the file on disk")
assert.Empty(t, nodeMeta.SelectorValues)
}

func TestNodeStore_Attest_Failure(t *testing.T) {
Expand All @@ -46,8 +47,9 @@ func TestNodeStore_Attest_Failure(t *testing.T) {
HashPath: t.TempDir(),
})

err := p.ns.Attest(context.Background(), ekWrapper)
nodeMeta, err := p.ns.Attest(context.Background(), ekWrapper)

assert.Error(t, err)
assert.Contains(t, err.Error(), "could not validate EK")
assert.Empty(t, nodeMeta.SelectorValues)
}