Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 1 | package main |
| 2 | |
| 3 | import ( |
Serge Bazanski | 0754ed8 | 2020-11-27 09:42:59 +0000 | [diff] [blame] | 4 | "context" |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 5 | "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 Bazanski | 4ded56a | 2020-08-01 22:01:05 +0200 | [diff] [blame] | 19 | // hspkiSigner returns a cfssl signer (CA) for HSPKI, by loading the CA |
| 20 | // cert/key from Kubernetes. |
Serge Bazanski | 0754ed8 | 2020-11-27 09:42:59 +0000 | [diff] [blame] | 21 | func (p *prodvider) hspkiSigner(ctx context.Context) (*local.Signer, error) { |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 22 | policy := &config.Signing{ |
| 23 | Profiles: map[string]*config.SigningProfile{ |
Serge Bazanski | 4ded56a | 2020-08-01 22:01:05 +0200 | [diff] [blame] | 24 | "client-server": &config.SigningProfile{ |
| 25 | Usage: []string{"signing", "key encipherment", "server auth", "client auth"}, |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 26 | ExpiryString: "30d", |
| 27 | }, |
| 28 | }, |
| 29 | Default: config.DefaultConfig(), |
| 30 | } |
| 31 | |
Serge Bazanski | 0754ed8 | 2020-11-27 09:42:59 +0000 | [diff] [blame] | 32 | secret, err := p.k8s.CoreV1().Secrets("cert-manager").Get(ctx, "pki-selfsigned-cert", metav1.GetOptions{}) |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 33 | 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 Bazanski | 4ded56a | 2020-08-01 22:01:05 +0200 | [diff] [blame] | 50 | // hspkiCreds returns a HSPKI certificate/key for an SSO user. The returned |
| 51 | // certificate is valida for both server and client usage. |
Serge Bazanski | 0754ed8 | 2020-11-27 09:42:59 +0000 | [diff] [blame] | 52 | func (p *prodvider) hspkiCreds(ctx context.Context, username string) (*pb.HSPKIKeys, error) { |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 53 | principal := fmt.Sprintf("%s.sso.hswaw.net", username) |
| 54 | |
Serge Bazanski | 0754ed8 | 2020-11-27 09:42:59 +0000 | [diff] [blame] | 55 | s, err := p.hspkiSigner(ctx) |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 56 | 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 Bazanski | 4ded56a | 2020-08-01 22:01:05 +0200 | [diff] [blame] | 87 | Profile: "client-server", |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 88 | 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 | } |