...
1 package spiffe
2
3 import (
4 "bytes"
5 "context"
6 "crypto"
7 "crypto/x509"
8 "encoding/pem"
9 "fmt"
10
11 intoto "github.com/in-toto/in-toto-golang/in_toto"
12 "github.com/spiffe/go-spiffe/v2/workloadapi"
13 )
14
15
19 type SVIDDetails struct {
20 PrivateKey crypto.Signer
21 Certificate *x509.Certificate
22 Intermediates []*x509.Certificate
23 }
24
25
29 type SVIDFetcher interface {
30 FetchX509Context(ctx context.Context) (*workloadapi.X509Context, error)
31 Close() error
32 }
33
34
38 func NewClient(ctx context.Context, socketPath string) (SVIDFetcher, error) {
39 return workloadapi.New(ctx, workloadapi.WithAddr(socketPath))
40 }
41
42
48 func GetSVID(ctx context.Context, client SVIDFetcher) (SVIDDetails, error) {
49 s := SVIDDetails{}
50 svidContext, err := client.FetchX509Context(ctx)
51 if err != nil {
52 return s, fmt.Errorf("error fetching spiffe x.509 context: %w", err)
53 }
54
55 svid := svidContext.DefaultSVID()
56 if len(svid.Certificates) <= 0 {
57 return s, fmt.Errorf("no certificates in svid")
58 }
59
60 if svid.PrivateKey == nil {
61 return s, fmt.Errorf("svid has no key")
62 }
63
64 s.PrivateKey = svid.PrivateKey
65 s.Certificate = svid.Certificates[0]
66 s.Intermediates = svid.Certificates[1:]
67 return s, nil
68 }
69
70
74 func (s SVIDDetails) InTotoKey() (intoto.Key, error) {
75 key := intoto.Key{}
76 keyBytes, err := x509.MarshalPKCS8PrivateKey(s.PrivateKey)
77 if err != nil {
78 return key, fmt.Errorf("failed to marshal svid key: %w", err)
79 }
80
81 keyPemBytes := pem.EncodeToMemory(&pem.Block{
82 Type: "PRIVATE KEY",
83 Bytes: keyBytes,
84 })
85
86 err = key.LoadKeyReaderDefaults(bytes.NewReader(keyPemBytes))
87 if err != nil {
88 return key, fmt.Errorf("failed to load key from spire: %w", err)
89 }
90
91 key.KeyVal.Certificate = string(pem.EncodeToMemory(&pem.Block{Bytes: s.Certificate.Raw, Type: "CERTIFICATE"}))
92 return key, nil
93 }
94
View as plain text