blob: 7222a8645da5a93581656525b11cae37a9498bfb [file] [log] [blame]
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +02001package main
2
3import (
4 "flag"
5 "io/ioutil"
6 "math/rand"
7 "net"
8 "os"
9 "time"
10
11 "github.com/cloudflare/cfssl/config"
12 "github.com/cloudflare/cfssl/signer/local"
13 "github.com/golang/glog"
14 "google.golang.org/grpc"
15 "k8s.io/client-go/kubernetes"
16
17 pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
18)
19
20var (
21 flagLDAPServer string
22 flagLDAPBindDN string
23 flagLDAPGroupSearchBase string
24 flagListenAddress string
25 flagKubernetesHost string
26
27 flagCACertificatePath string
28 flagCAKeyPath string
29 flagKubeCACertificatePath string
30
31 flagProdviderCN string
32)
33
34func init() {
35 flag.Set("logtostderr", "true")
36}
37
38type prodvider struct {
39 sign *local.Signer
40 k8s *kubernetes.Clientset
41 srv *grpc.Server
42 kubeCAPEM []byte
43}
44
45func newProdvider() *prodvider {
46 policy := &config.Signing{
47 Profiles: map[string]*config.SigningProfile{
48 "server": &config.SigningProfile{
49 Usage: []string{"signing", "key encipherment", "server auth"},
50 ExpiryString: "30d",
51 },
52 "client": &config.SigningProfile{
53 Usage: []string{"signing", "key encipherment", "client auth"},
54 ExpiryString: "30d",
55 },
56 "client-server": &config.SigningProfile{
57 Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
58 ExpiryString: "30d",
59 },
60 },
61 Default: config.DefaultConfig(),
62 }
63
64 sign, err := local.NewSignerFromFile(flagCACertificatePath, flagCAKeyPath, policy)
65 if err != nil {
66 glog.Exitf("Could not create signer: %v", err)
67 }
68
69 kubeCAPEM, err := ioutil.ReadFile(flagKubeCACertificatePath)
70 if err != nil {
71 glog.Exitf("Could not read kube CA cert path: %v")
72 }
73
74 return &prodvider{
75 sign: sign,
76 kubeCAPEM: kubeCAPEM,
77 }
78}
79
80// Timebomb restarts the prodvider after a deadline, usually 7 days +/- 4 days.
81// This is to ensure we serve with up-to-date certificates and that the service
82// can still come up after restart.
83func timebomb(srv *grpc.Server) {
84 deadline := time.Now()
85 deadline = deadline.Add(3 * 24 * time.Hour)
86 rand.Seed(time.Now().UnixNano())
87 jitter := rand.Intn(8 * 24 * 60 * 60)
88 deadline = deadline.Add(time.Duration(jitter) * time.Second)
89
90 glog.Infof("Timebomb deadline set to %v", deadline)
91
92 t := time.NewTicker(time.Minute)
93 for {
94 <-t.C
95 if time.Now().After(deadline) {
96 break
97 }
98 }
99
100 // Start killing connections, and wait one minute...
101 go srv.GracefulStop()
102 <-t.C
103 glog.Infof("Timebomb deadline exceeded, restarting.")
104 os.Exit(0)
105}
106
107func main() {
108 flag.StringVar(&flagLDAPServer, "ldap_server", "ldap.hackerspace.pl:636", "Address of LDAP server")
109 flag.StringVar(&flagLDAPBindDN, "ldap_bind_dn", "uid=%s,ou=People,dc=hackerspace,dc=pl", "LDAP Bind DN")
110 flag.StringVar(&flagLDAPGroupSearchBase, "ldap_group_search_base_dn", "ou=Group,dc=hackerspace,dc=pl", "LDAP Group Search Base DN")
111 flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:8080", "gRPC listen address")
112 flag.StringVar(&flagKubernetesHost, "kubernetes_host", "k0.hswaw.net:4001", "Kubernetes API host")
113
114 flag.StringVar(&flagCACertificatePath, "ca_certificate_path", "", "CA certificate path (for signer)")
115 flag.StringVar(&flagCAKeyPath, "ca_key_path", "", "CA key path (for signer)")
116 flag.StringVar(&flagKubeCACertificatePath, "kube_ca_certificate_path", "", "CA certificate path (for checking kube apiserver)")
117
118 flag.StringVar(&flagProdviderCN, "prodvider_cn", "prodvider.hswaw.net", "CN of certificate that prodvider will use")
119 flag.Parse()
120
121 if flagCACertificatePath == "" || flagCAKeyPath == "" {
122 glog.Exitf("CA certificate and key must be provided")
123 }
124
125 p := newProdvider()
126 err := p.kubernetesConnect()
127 if err != nil {
128 glog.Exitf("Could not connect to kubernetes: %v", err)
129 }
130 creds := p.selfCreds()
131
132 // Start serving gRPC
133 grpcLis, err := net.Listen("tcp", flagListenAddress)
134 if err != nil {
135 glog.Exitf("Could not listen for gRPC on %q: %v", flagListenAddress, err)
136 }
137
138 glog.Infof("Starting gRPC on %q...", flagListenAddress)
139 grpcSrv := grpc.NewServer(creds)
140
141 pb.RegisterProdviderServer(grpcSrv, p)
142
143 go timebomb(grpcSrv)
144
145 err = grpcSrv.Serve(grpcLis)
146 if err != nil {
147 glog.Exitf("Could not serve gRPC: %v", err)
148 }
149}