github.com/outbrain/consul@v1.4.5/agent/connect/csr.go (about) 1 package connect 2 3 import ( 4 "bytes" 5 "crypto" 6 "crypto/rand" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/asn1" 10 "encoding/pem" 11 "net/url" 12 ) 13 14 // CreateCSR returns a CSR to sign the given service along with the PEM-encoded 15 // private key for this certificate. 16 func CreateCSR(uri CertURI, privateKey crypto.Signer, extensions ...pkix.Extension) (string, error) { 17 template := &x509.CertificateRequest{ 18 URIs: []*url.URL{uri.URI()}, 19 SignatureAlgorithm: x509.ECDSAWithSHA256, 20 ExtraExtensions: extensions, 21 } 22 23 // Create the CSR itself 24 var csrBuf bytes.Buffer 25 bs, err := x509.CreateCertificateRequest(rand.Reader, template, privateKey) 26 if err != nil { 27 return "", err 28 } 29 30 err = pem.Encode(&csrBuf, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: bs}) 31 if err != nil { 32 return "", err 33 } 34 35 return csrBuf.String(), nil 36 } 37 38 // CreateCSR returns a CA CSR to sign the given service along with the PEM-encoded 39 // private key for this certificate. 40 func CreateCACSR(uri CertURI, privateKey crypto.Signer) (string, error) { 41 ext, err := CreateCAExtension() 42 if err != nil { 43 return "", err 44 } 45 46 return CreateCSR(uri, privateKey, ext) 47 } 48 49 // CreateCAExtension creates a pkix.Extension for the x509 Basic Constraints 50 // IsCA field () 51 func CreateCAExtension() (pkix.Extension, error) { 52 type basicConstraints struct { 53 IsCA bool `asn1:"optional"` 54 MaxPathLen int `asn1:"optional"` 55 } 56 basicCon := basicConstraints{IsCA: true, MaxPathLen: 0} 57 bitstr, err := asn1.Marshal(basicCon) 58 if err != nil { 59 return pkix.Extension{}, err 60 } 61 62 return pkix.Extension{ 63 Id: []int{2, 5, 29, 19}, // from x509 package 64 Critical: true, 65 Value: bitstr, 66 }, nil 67 }