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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 | package main
import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
"fmt"
)
// In practice, these 4 consts would come from the agent config
const certString = `-----BEGIN CERTIFICATE-----
MIICNzCCAaKgAwIBAgIBADALBgkqhkiG9w0BAQUwQzENMAsGA1UEChMEanVqdTEy
MDAGA1UEAwwpanVqdS1nZW5lcmF0ZWQgQ0EgZm9yIGVudmlyb25tZW50ICJsb2Nh
bCIwHhcNMTUwMzE2MDMzMjE3WhcNMjUwMzIzMDMzMjE3WjAbMQ0wCwYDVQQKEwRq
dWp1MQowCAYDVQQDEwEqMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChFRws
Ogim0rVIfc4zCxhrvQgsGcp/hkfHaT+XTSRDRnxmcjAD3lKR6iSB47T/VjPDcs05
lyMywWFJH81pk+tIU2h1WsVnlaJJ5NCTyzBJvvmPd5LiRjnhMzqH/0RBv6nFxjuo
zEKy7EorrUDRaLxR8J6mt9oZpIRm4FsKws5bgQIDAQABo2cwZTAOBgNVHQ8BAf8E
BAMCAKgwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFIeVCNOzzXsiRRD6
1bSdc++Ng5ngMB8GA1UdIwQYMBaAFJ3s0MEePRRvXU7nxldZnpo/pbwEMAsGCSqG
SIb3DQEBBQOBgQBD/KUKujUf6OK95kidqu6zEK/79TGfTLxcOqALFmBqhzUiznb5
sYD9b99DsYTy9yoQniVgiX1TFEn/t0OmQNxGDvRF8I6svGl192X+ZJnxCNLN7tjZ
GyKXuekS+6wVhDYCsTfxQ/Eeom73+1/CFg36pY+mofAvxXepee8U3KkYNQ==
-----END CERTIFICATE-----
`
const privKeyString = `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQChFRwsOgim0rVIfc4zCxhrvQgsGcp/hkfHaT+XTSRDRnxmcjAD
3lKR6iSB47T/VjPDcs05lyMywWFJH81pk+tIU2h1WsVnlaJJ5NCTyzBJvvmPd5Li
RjnhMzqH/0RBv6nFxjuozEKy7EorrUDRaLxR8J6mt9oZpIRm4FsKws5bgQIDAQAB
AoGAUU3tbWlRapqaA9/0DxF/nwnHsTLHYfyuCDnYbg7yyb4vFip2j81MkffDu4fq
mKKy9+jfKz1c98Zhy13w+WQ+8fJ9YoeRXdbJ3P6uKi4suQOqOSnZLafJQroEdcOQ
qf72PcGjPMXBInLZauI+OwSfsTNtmwjEJMdY7YjzshUz5d0CQQDDxpzNeE2z68AB
6BKd7WXIvAdeghCD0YK+EA0UJOQ40Opk8EQreMJX/Hz1m0H5rmF7yEdRrb0bzirx
oFVbk6M/AkEA0qJjMofaUda0KxbO850mSFOcyqStgJJ/E1u/phRDYSAJALAhDP82
u+HJZ3wZpYgn2/wktArO97Esdo47Zd4RPwJBAIwlquw/2cgZ1NrIikM5xapcSB40
l6P1oFV04hfwjNvLWnAlu3cvPFiGK+IaYbFeTvSwm7Vx3TWBciaEs3YaCzsCQQCC
Uf5V8T/eipyGXGJGz+Azt6e2qRTAC+ObspRsyPS3Tv7C8jZAuFbA//2AjYPAqvEe
Zm6/BkDvdysvXujZKgA5AkBtvBzieFD6Cw33YBsGHoRzTa+DxV3sPEV/H7zdfLQW
Y5i9oHlYP9WxJzHm5IF7tznpvxOdkUHtkCqP1d6Tir+W
-----END RSA PRIVATE KEY-----
`
const caPrivKeyString = `-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDlJwCzGRKi0AkwkRpgXFdvNf7SIaVEO5kZwYq4p1Izw3KcCiuO
goI+nsJYoYHMsaHj1Gv6GOcvdyrH5zboIibsVAQrHdmb3BkhCLBRgyuRQX9lwtEV
8uNwX+h/L6l8jX7/MGlWTq1rVQ+c8sakYprht4an43rCkE/vj2SlNr5RUQIDAQAB
AoGBAKvEaaTWRX7fXBQYoGHctfl5yvHuIHieB+wjhH1Xhqmgdrd6dB3VvBV+YYWY
QriR6hziLLICmsCcnefMa/7jIrKWJAoXOYVB/MJSWkKZ1rZUxaNfWyqtu3k1MJcE
L5gZ6G7zm3fojqOHpAjyWu9eDW7BPHCxKIV+8c4OcnCioGi1AkEA+Q90EqijAuW6
FkU67Ot01KwxAJC8PjFyAz+g0m/Gu3aSfq/a9K5RYhwd+oclzzvIA37rCWZVeOVL
Bp4H//7g/wJBAOuJi6oSf+uEn0oxUoaMJuRRYk9Uzd5/q11v6hSBVi0/NJXHqKhV
Y0zkuXFIrDx50GIpTFV1fd585xnNA1Zafa8CQQCHytkqYy+doMs44T4jdq0YV1nQ
SRmZfzP+eW6hzbe49gkhcZgb1/8fUt01fwIqXxnKbiSP12+6nqmtTfRmqvzZAkEA
4i257T5IkoxPPjqwyb1KF5PDOPTxoEiu8VHn0XsFmvuH7pDE96jPa2Z0YUFtC8Ha
Bnkr8SCbFwyQC2mgW8sXxwJBAON+JfcZ72ks4tUSDu4fX8+awEkp9KQJerHy/Ib3
uFJkC8irZQ0M6pEZvWOy64DFvfcu8mV+HvSXP/GERYiWqto=
-----END RSA PRIVATE KEY-----
`
const caCertString = `-----BEGIN CERTIFICATE-----
MIICWzCCAcagAwIBAgIBADALBgkqhkiG9w0BAQUwQzENMAsGA1UEChMEanVqdTEy
MDAGA1UEAwwpanVqdS1nZW5lcmF0ZWQgQ0EgZm9yIGVudmlyb25tZW50ICJsb2Nh
bCIwHhcNMTUwMzE2MDMzMjEyWhcNMjUwMzIzMDMzMjEyWjBDMQ0wCwYDVQQKEwRq
dWp1MTIwMAYDVQQDDClqdWp1LWdlbmVyYXRlZCBDQSBmb3IgZW52aXJvbm1lbnQg
ImxvY2FsIjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5ScAsxkSotAJMJEa
YFxXbzX+0iGlRDuZGcGKuKdSM8NynAorjoKCPp7CWKGBzLGh49Rr+hjnL3cqx+c2
6CIm7FQEKx3Zm9wZIQiwUYMrkUF/ZcLRFfLjcF/ofy+pfI1+/zBpVk6ta1UPnPLG
pGKa4beGp+N6wpBP749kpTa+UVECAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgCkMA8G
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ3s0MEePRRvXU7nxldZnpo/pbwEMB8G
A1UdIwQYMBaAFJ3s0MEePRRvXU7nxldZnpo/pbwEMAsGCSqGSIb3DQEBBQOBgQCN
q9NFWsYaoym0aivQ7dqHY88K4ehxPipN4RPI8gPpBIaE9LVas1JyYIsk7iM4y6pY
RIs1oi/x36lxvDuZUCZCLmUrnWRO4hhCwzf3dPOyu6meAkp9AgTaR8x6Z5TKZ57o
u4yT2zmz3Yo9SPab8+31F8MABLloZ8ay0txODOn31Q==
-----END CERTIFICATE-----
`
func decodeBlock(raw []byte, expectedType string) []byte {
block, _ := pem.Decode(raw)
if block == nil {
panic("PEM decode failed")
}
if block.Type != expectedType {
panic(fmt.Sprintf("unexpected block type: %q", block.Type))
}
return block.Bytes
}
func panicOnErr(label string, err error) {
if err != nil {
panic(fmt.Sprintf("%s: %v", label, err))
}
}
func main() {
// Parse cert to update.
cert, err := x509.ParseCertificate(decodeBlock([]byte(certString), "CERTIFICATE"))
panicOnErr("ParseCertificate", err)
fmt.Println("starting DNSNames:", cert.DNSNames)
// Extract and parse key.
key, err := x509.ParsePKCS1PrivateKey(decodeBlock([]byte(privKeyString), "RSA PRIVATE KEY"))
panicOnErr("ParsePKCS1PrivateKey", err)
// Parse CA cert.
caCert, err := x509.ParseCertificate(decodeBlock([]byte(caCertString), "CERTIFICATE"))
panicOnErr("ParseCertificate (CA)", err)
// Parse CA private key.
caKey, err := x509.ParsePKCS1PrivateKey(decodeBlock([]byte(caPrivKeyString), "RSA PRIVATE KEY"))
panicOnErr("ParsePKCS1PrivateKey (CA)", err)
// Update starts here...
cert.DNSNames = []string{"localhost", "juju-apiserver", "juju-mongodb"}
certDER, err := x509.CreateCertificate(rand.Reader, cert, caCert, &key.PublicKey, caKey)
panicOnErr("CreateCertificate", err)
certPEMData := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: certDER,
})
fmt.Println("\nupdated cert:\n", string(certPEMData))
}
|