-
Notifications
You must be signed in to change notification settings - Fork 458
/
gen.go
101 lines (87 loc) · 2.36 KB
/
gen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package gen
import (
"context"
stdlibx509 "crypto/x509"
"encoding/pem"
"fmt"
"log"
stdlibnet "net"
"time"
"github.com/autonomy/dianemo/src/initramfs/cmd/rotd/proto"
"github.com/autonomy/dianemo/src/initramfs/pkg/crypto/x509"
"github.com/autonomy/dianemo/src/initramfs/pkg/net"
"github.com/autonomy/dianemo/src/initramfs/pkg/userdata"
"google.golang.org/grpc"
)
// Generator represents the OS identity generator.
type Generator struct {
client proto.ROTDClient
}
// NewGenerator initializes a Generator with a preconfigured grpc.ClientConn.
func NewGenerator(conn *grpc.ClientConn) (g *Generator) {
client := proto.NewROTDClient(conn)
return &Generator{
client: client,
}
}
// Certificate implements the proto.ROTDClient interface.
func (g *Generator) Certificate(in *proto.CertificateRequest) (resp *proto.CertificateResponse, err error) {
ctx := context.Background()
resp, err = g.client.Certificate(ctx, in)
if err != nil {
return
}
return resp, err
}
// Identity creates a CSR and sends it to a Root of Trust for signing.
// The Root of Trust responds with a signed certificate.
func (g *Generator) Identity(data *userdata.Security) (err error) {
key, err := x509.NewKey()
if err != nil {
return
}
data.OS.Identity = &x509.PEMEncodedCertificateAndKey{}
data.OS.Identity.Key = key.KeyPEM
pemBlock, _ := pem.Decode(key.KeyPEM)
if pemBlock == nil {
return fmt.Errorf("failed to decode key")
}
keyEC, err := stdlibx509.ParseECPrivateKey(pemBlock.Bytes)
if err != nil {
return
}
addr, err := net.IP()
if err != nil {
return
}
opts := []x509.Option{}
ips := []stdlibnet.IP{addr}
opts = append(opts, x509.IPAddresses(ips))
opts = append(opts, x509.NotAfter(time.Now().Add(time.Duration(8760)*time.Hour)))
csr, err := x509.NewCertificateSigningRequest(keyEC, opts...)
if err != nil {
return
}
req := &proto.CertificateRequest{
Csr: csr.X509CertificateRequestPEM,
}
return poll(g, req, data.OS.Identity)
}
func poll(g *Generator, in *proto.CertificateRequest, data *x509.PEMEncodedCertificateAndKey) (err error) {
timeout := time.NewTimer(time.Minute * 5).C
tick := time.NewTicker(time.Second * 5).C
for {
select {
case <-timeout:
return fmt.Errorf("timeout waiting for certificate")
case <-tick:
crt, _err := g.Certificate(in)
if _err != nil {
log.Println(_err)
continue
}
data.Crt = crt.Bytes
return nil
}
}
}