1 package main
2
3 import (
4 "crypto/ecdsa"
5 "crypto/rand"
6 "crypto/x509"
7 "crypto/x509/pkix"
8 "errors"
9 "fmt"
10 "os"
11 "path/filepath"
12 "syscall"
13
14 "k8s.io/apimachinery/pkg/util/validation"
15 "k8s.io/apimachinery/pkg/util/validation/field"
16
17 "github.com/linkerd/linkerd2/pkg/tls"
18 log "github.com/sirupsen/logrus"
19 )
20
21 const (
22 envDir = "LINKERD2_PROXY_IDENTITY_DIR"
23 envLocalName = "LINKERD2_PROXY_IDENTITY_LOCAL_NAME"
24 envTrustAnchors = "LINKERD2_PROXY_IDENTITY_TRUST_ANCHORS"
25 )
26
27 func main() {
28 dir := os.Getenv(envDir)
29 keyPath, csrPath, err := checkEndEntityDir(dir)
30 if err != nil {
31 log.Fatalf("Invalid end-entity directory: %s", err)
32 }
33
34 if _, err := loadVerifier(os.Getenv(envTrustAnchors)); err != nil {
35 log.Fatalf("Failed to load trust anchors: %s", err)
36 }
37
38 key, err := generateAndStoreKey(keyPath)
39 if err != nil {
40 log.Fatal(err.Error())
41 }
42
43 name := os.Getenv(envLocalName)
44 if _, err := generateAndStoreCSR(csrPath, name, key); err != nil {
45 log.Fatal(err.Error())
46 }
47
48 runProxy()
49 }
50
51 func loadVerifier(pem string) (verify x509.VerifyOptions, err error) {
52 if pem == "" {
53 err = fmt.Errorf("'%s' must be set", envTrustAnchors)
54 return
55 }
56
57 verify.Roots, err = tls.DecodePEMCertPool(pem)
58 return
59 }
60
61
62
63
64
65
66
67
68
69
70
71 func checkEndEntityDir(dir string) (string, string, error) {
72 if dir == "" {
73 return "", "", errors.New("no end entity directory specified")
74 }
75
76 s, err := os.Stat(dir)
77 if err != nil {
78 return "", "", err
79 }
80 if !s.IsDir() {
81 return "", "", fmt.Errorf("not a directory: %s", dir)
82 }
83
84 keyPath := filepath.Join(dir, "key.p8")
85 if err = checkNotExists(keyPath); err != nil {
86 log.Infof("Found pre-existing key: %s", keyPath)
87 }
88
89 csrPath := filepath.Join(dir, "csr.der")
90 if err = checkNotExists(csrPath); err != nil {
91 log.Infof("Found pre-existing CSR: %s", csrPath)
92 }
93
94 return keyPath, csrPath, nil
95 }
96
97 func checkNotExists(p string) (err error) {
98 _, err = os.Stat(p)
99 if err == nil {
100 err = fmt.Errorf("already exists: %s", p)
101 } else if os.IsNotExist(err) {
102 err = nil
103 }
104 return
105 }
106
107 func generateAndStoreKey(p string) (key *ecdsa.PrivateKey, err error) {
108
109
110
111
112 key, err = tls.GenerateKey()
113 if err != nil {
114 return
115 }
116
117 pemb := tls.EncodePrivateKeyP8(key)
118 err = os.WriteFile(p, pemb, 0600)
119 return
120 }
121
122 func generateAndStoreCSR(p, id string, key *ecdsa.PrivateKey) ([]byte, error) {
123 if id == "" {
124 return nil, errors.New("a non-empty identity is required")
125 }
126
127 if err := validation.IsFullyQualifiedDomainName(field.NewPath(""), id).ToAggregate(); err != nil {
128 return nil, fmt.Errorf("%s a fully qualified DNS name is required", id)
129 }
130
131 csr := x509.CertificateRequest{
132 Subject: pkix.Name{CommonName: id},
133 DNSNames: []string{id},
134 }
135 csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, key)
136 if err != nil {
137 return nil, fmt.Errorf("failed to create CSR: %w", err)
138 }
139
140 if err = os.WriteFile(p, csrb, 0600); err != nil {
141 return nil, fmt.Errorf("failed to write CSR: %w", err)
142 }
143
144 return csrb, nil
145 }
146
147 func runProxy() {
148
149
150 err := syscall.Exec("/usr/lib/linkerd/linkerd2-proxy", []string{}, os.Environ())
151 if err != nil {
152 log.Fatalf("Failed to run proxy: %s", err)
153 }
154 }
155
View as plain text