-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
116 lines (95 loc) · 3.37 KB
/
main.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2024 VEXXHOST, Inc.
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"os/exec"
"github.com/kelseyhightower/envconfig"
log "github.com/sirupsen/logrus"
"github.com/vexxhost/pod-tls-sidecar/pkg/tls"
"k8s.io/client-go/rest"
"libvirt.org/go/libvirt"
"github.com/vexxhost/libvirt-tls-sidecar/pkg/template"
)
type IssuerInfo struct {
Kind string `envconfig:"ISSUER_KIND" required:"true"`
Name string `envconfig:"ISSUER_NAME" required:"true"`
}
func main() {
var apiIssuer template.IssuerInfo
if err := envconfig.Process("API", &apiIssuer); err != nil {
log.Fatal(err)
}
var vncIssuer template.IssuerInfo
if err := envconfig.Process("VNC", &vncIssuer); err != nil {
log.Fatal(err)
}
config, err := rest.InClusterConfig()
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
go createCertificateSpec(ctx, "api", &apiIssuer, tls.WithRestConfig(config), tls.WithPaths(&tls.WritePathConfig{
CertificateAuthorityPaths: []string{"/etc/pki/CA/cacert.pem", "/etc/pki/qemu/ca-cert.pem"},
CertificatePaths: []string{"/etc/pki/libvirt/servercert.pem", "/etc/pki/libvirt/clientcert.pem", "/etc/pki/qemu/server-cert.pem", "/etc/pki/qemu/client-cert.pem"},
CertificateKeyPaths: []string{"/etc/pki/libvirt/private/serverkey.pem", "/etc/pki/libvirt/private/clientkey.pem", "/etc/pki/qemu/server-key.pem", "/etc/pki/qemu/client-key.pem"},
}), tls.WithOnUpdate(func() {
cmd := exec.Command("virt-admin", "server-update-tls", "libvirtd")
out, err := cmd.CombinedOutput()
if err != nil {
log.WithError(err).WithField("output", string(out)).Error("failed to reload tls configuration for api")
return
}
log.WithField("output", string(out)).Info("reloaded tls configuration for api")
}))
go createCertificateSpec(ctx, "vnc", &vncIssuer, tls.WithRestConfig(config), tls.WithPaths(&tls.WritePathConfig{
CertificateAuthorityPaths: []string{"/etc/pki/libvirt-vnc/ca-cert.pem"},
CertificatePaths: []string{"/etc/pki/libvirt-vnc/server-cert.pem"},
CertificateKeyPaths: []string{"/etc/pki/libvirt-vnc/server-key.pem"},
}), tls.WithOnUpdate(func() {
conn, err := libvirt.NewConnect("qemu:///system")
if err != nil {
log.WithError(err).Error("failed to connect to libvirt")
return
}
defer conn.Close()
// list all domains
domains, err := conn.ListAllDomains(libvirt.CONNECT_LIST_DOMAINS_ACTIVE)
if err != nil {
log.WithError(err).Error("failed to list domains")
return
}
for _, domain := range domains {
response, err := domain.QemuMonitorCommand(`{"execute": "display-reload", "arguments":{"type": "vnc", "tls-certs": true}}`, libvirt.DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT)
if err != nil {
log.WithError(err).Error("failed to reload tls configuration for vnc")
continue
}
log.WithField("response", response).Info("reloaded tls configuration for vnc")
}
}))
<-ctx.Done()
}
func createCertificateSpec(ctx context.Context, name string, issuer *template.IssuerInfo, opts ...tls.Option) {
tmpl, err := template.New(name, issuer)
if err != nil {
log.Fatal(err)
}
args := []tls.Option{
tls.WithTemplate(tmpl),
}
args = append(args, opts...)
config, err := tls.NewConfig(args...)
if err != nil {
log.Fatal(err)
}
manager, err := tls.NewManager(config)
if err != nil {
log.Fatal(err)
}
err = manager.Create(ctx)
if err != nil {
log.Fatal(err)
}
manager.Watch(ctx)
}