17208: Merge branch 'master'
[arvados.git] / lib / boot / cert.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package boot
6
7 import (
8         "context"
9         "fmt"
10         "io/ioutil"
11         "net"
12         "path/filepath"
13 )
14
15 // Create a root CA key and use it to make a new server
16 // certificate+key pair.
17 //
18 // In future we'll make one root CA key per host instead of one per
19 // cluster, so it only needs to be imported to a browser once for
20 // ongoing dev/test usage.
21 type createCertificates struct{}
22
23 func (createCertificates) String() string {
24         return "certificates"
25 }
26
27 func (createCertificates) Run(ctx context.Context, fail func(error), super *Supervisor) error {
28         var san string
29         if net.ParseIP(super.ListenHost) != nil {
30                 san = fmt.Sprintf("IP:%s", super.ListenHost)
31         } else {
32                 san = fmt.Sprintf("DNS:%s", super.ListenHost)
33         }
34
35         // Generate root key
36         err := super.RunProgram(ctx, super.tempdir, nil, nil, "openssl", "genrsa", "-out", "rootCA.key", "4096")
37         if err != nil {
38                 return err
39         }
40         // Generate a self-signed root certificate
41         err = super.RunProgram(ctx, super.tempdir, nil, nil, "openssl", "req", "-x509", "-new", "-nodes", "-key", "rootCA.key", "-sha256", "-days", "3650", "-out", "rootCA.crt", "-subj", "/C=US/ST=MA/O=Example Org/CN=localhost")
42         if err != nil {
43                 return err
44         }
45         // Generate server key
46         err = super.RunProgram(ctx, super.tempdir, nil, nil, "openssl", "genrsa", "-out", "server.key", "2048")
47         if err != nil {
48                 return err
49         }
50         // Build config file for signing request
51         defaultconf, err := ioutil.ReadFile("/etc/ssl/openssl.cnf")
52         if err != nil {
53                 return err
54         }
55         err = ioutil.WriteFile(filepath.Join(super.tempdir, "server.cfg"), append(defaultconf, []byte(fmt.Sprintf("\n[SAN]\nsubjectAltName=DNS:localhost,DNS:localhost.localdomain,%s\n", san))...), 0644)
56         if err != nil {
57                 return err
58         }
59         // Generate signing request
60         err = super.RunProgram(ctx, super.tempdir, nil, nil, "openssl", "req", "-new", "-sha256", "-key", "server.key", "-subj", "/C=US/ST=MA/O=Example Org/CN=localhost", "-reqexts", "SAN", "-config", "server.cfg", "-out", "server.csr")
61         if err != nil {
62                 return err
63         }
64         // Sign certificate
65         err = super.RunProgram(ctx, super.tempdir, nil, nil, "openssl", "x509", "-req", "-in", "server.csr", "-CA", "rootCA.crt", "-CAkey", "rootCA.key", "-CAcreateserial", "-out", "server.crt", "-extfile", "server.cfg", "-extensions", "SAN", "-days", "3650", "-sha256")
66         if err != nil {
67                 return err
68         }
69         return nil
70 }