-
Notifications
You must be signed in to change notification settings - Fork 18
/
certificates.go
93 lines (76 loc) · 2.52 KB
/
certificates.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
package resources
import (
"context"
"encoding/json"
"encoding/pem"
"fmt"
"net/http"
"os"
"path/filepath"
"github.com/canonical/lxd/lxd/response"
"github.com/canonical/microcluster/client"
"github.com/canonical/microcluster/internal/state"
"github.com/canonical/microcluster/rest"
"github.com/canonical/microcluster/rest/access"
"github.com/canonical/microcluster/rest/types"
)
var clusterCertificatesCmd = rest.Endpoint{
AllowedBeforeInit: true,
Path: "cluster/certificates",
Put: rest.EndpointAction{Handler: clusterCertificatesPut, AccessHandler: access.AllowAuthenticated},
}
func clusterCertificatesPut(s *state.State, r *http.Request) response.Response {
req := types.ClusterCertificatePut{}
// Parse the request.
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
return response.BadRequest(err)
}
// Forward the request to all other nodes if we are the first.
if !client.IsNotification(r) && s.Database.IsOpen() {
cluster, err := s.Cluster(true)
if err != nil {
return response.SmartError(err)
}
err = cluster.Query(s.Context, true, func(ctx context.Context, c *client.Client) error {
return c.UpdateClusterCertificate(ctx, req)
})
if err != nil {
return response.SmartError(fmt.Errorf("Failed to update cluster certificate on peers: %w", err))
}
}
certBlock, _ := pem.Decode([]byte(req.PublicKey))
if certBlock == nil {
return response.BadRequest(fmt.Errorf("Certificate must be base64 encoded PEM certificate"))
}
keyBlock, _ := pem.Decode([]byte(req.PrivateKey))
if keyBlock == nil {
return response.BadRequest(fmt.Errorf("Private key must be base64 encoded PEM key"))
}
// If a CA was specified, validate that as well.
if req.CA != "" {
caBlock, _ := pem.Decode([]byte(req.CA))
if caBlock == nil {
return response.BadRequest(fmt.Errorf("CA must be base64 encoded PEM key"))
}
err = os.WriteFile(filepath.Join(s.OS.StateDir, "cluster.ca"), []byte(req.CA), 0650)
if err != nil {
return response.SmartError(err)
}
}
// Write the keypair to the state directory.
err = os.WriteFile(filepath.Join(s.OS.StateDir, "cluster.crt"), []byte(req.PublicKey), 0650)
if err != nil {
return response.SmartError(err)
}
err = os.WriteFile(filepath.Join(s.OS.StateDir, "cluster.key"), []byte(req.PrivateKey), 0650)
if err != nil {
return response.SmartError(err)
}
// Load the new cluster cert from the state directory on this node.
err = state.ReloadClusterCert()
if err != nil {
return response.SmartError(err)
}
return response.EmptySyncResponse
}