blob: fabf84dba6391df5bc4198946879d0ec650584e0 [file] [log] [blame]
Serge Bazanskif3312ef2020-08-01 17:15:52 +02001package main
2
3import (
Serge Bazanski0754ed82020-11-27 09:42:59 +00004 "context"
Serge Bazanskif3312ef2020-08-01 17:15:52 +02005 "encoding/pem"
6 "fmt"
7 "time"
8
9 "github.com/cloudflare/cfssl/config"
10 "github.com/cloudflare/cfssl/csr"
11 "github.com/cloudflare/cfssl/helpers"
12 "github.com/cloudflare/cfssl/signer"
13 "github.com/cloudflare/cfssl/signer/local"
14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
16 pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
17)
18
Serge Bazanski4ded56a2020-08-01 22:01:05 +020019// hspkiSigner returns a cfssl signer (CA) for HSPKI, by loading the CA
20// cert/key from Kubernetes.
Serge Bazanski0754ed82020-11-27 09:42:59 +000021func (p *prodvider) hspkiSigner(ctx context.Context) (*local.Signer, error) {
Serge Bazanskif3312ef2020-08-01 17:15:52 +020022 policy := &config.Signing{
23 Profiles: map[string]*config.SigningProfile{
Serge Bazanski4ded56a2020-08-01 22:01:05 +020024 "client-server": &config.SigningProfile{
25 Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
Serge Bazanskif3312ef2020-08-01 17:15:52 +020026 ExpiryString: "30d",
27 },
28 },
29 Default: config.DefaultConfig(),
30 }
31
Serge Bazanski0754ed82020-11-27 09:42:59 +000032 secret, err := p.k8s.CoreV1().Secrets("cert-manager").Get(ctx, "pki-selfsigned-cert", metav1.GetOptions{})
Serge Bazanskif3312ef2020-08-01 17:15:52 +020033 if err != nil {
34 return nil, fmt.Errorf("hspki secret get failed: %w", err)
35 }
36
37 parsedCa, err := helpers.ParseCertificatePEM(secret.Data["tls.crt"])
38 if err != nil {
39 return nil, fmt.Errorf("when parsing tls.crt: %w", err)
40 }
41
42 priv, err := helpers.ParsePrivateKeyPEMWithPassword(secret.Data["tls.key"], nil)
43 if err != nil {
44 return nil, fmt.Errorf("when parsing tls.key: %w", err)
45 }
46
47 return local.NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
48}
49
Serge Bazanski4ded56a2020-08-01 22:01:05 +020050// hspkiCreds returns a HSPKI certificate/key for an SSO user. The returned
51// certificate is valida for both server and client usage.
Serge Bazanski0754ed82020-11-27 09:42:59 +000052func (p *prodvider) hspkiCreds(ctx context.Context, username string) (*pb.HSPKIKeys, error) {
Serge Bazanskif3312ef2020-08-01 17:15:52 +020053 principal := fmt.Sprintf("%s.sso.hswaw.net", username)
54
Serge Bazanski0754ed82020-11-27 09:42:59 +000055 s, err := p.hspkiSigner(ctx)
Serge Bazanskif3312ef2020-08-01 17:15:52 +020056 if err != nil {
57 return nil, fmt.Errorf("hspkiSigner: %w", err)
58 }
59
60 signerCert, _ := s.Certificate("", "")
61 req := &csr.CertificateRequest{
62 CN: principal,
63 KeyRequest: &csr.BasicKeyRequest{
64 A: "rsa",
65 S: 4096,
66 },
67 Names: []csr.Name{
68 {
69 O: "prodvider",
70 OU: fmt.Sprintf("Prodvider HSPKI Cert for %s", username),
71 },
72 },
73 }
74
75 g := &csr.Generator{
76 Validator: func(req *csr.CertificateRequest) error { return nil },
77 }
78
79 csrPEM, keyPEM, err := g.ProcessRequest(req)
80 if err != nil {
81 return nil, fmt.Errorf("when making CSR: %w", err)
82 }
83
84 signReq := signer.SignRequest{
85 Hosts: []string{},
86 Request: string(csrPEM),
Serge Bazanski4ded56a2020-08-01 22:01:05 +020087 Profile: "client-server",
Serge Bazanskif3312ef2020-08-01 17:15:52 +020088 NotAfter: time.Now().Add(9 * time.Hour),
89 }
90
91 certPEM, err := s.Sign(signReq)
92 if err != nil {
93 return nil, fmt.Errorf("when issuing certificate: %w", err)
94 }
95
96 caPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: signerCert.Raw})
97
98 return &pb.HSPKIKeys{
99 Ca: caPEM,
100 Cert: certPEM,
101 Key: keyPEM,
102 Principal: principal,
103 }, nil
104}