Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
var result *bundler.Bundle
switch matched[0] {
case "domain":
bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], bf)
bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], "443", bf)
if err != nil {
log.Warningf("couldn't bundle from remote: %v", err)
return err
Expand Down
52 changes: 48 additions & 4 deletions bundler/bundle_from_remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package bundler
// This test file contains tests on checking the correctness of BundleFromRemote
import (
"flag"
"io/ioutil"
"net"
"net/http"
"testing"

"github.com/cloudflare/cfssl/helpers/testsuite"
"github.com/cloudflare/cfssl/ubiquity"
)

Expand Down Expand Up @@ -39,6 +43,14 @@ const (
InvalidIP = "300.300.300.300"
)

var (
certFile = "testdata/cert/cert_chain.crt"
keyFile = "testdata/cert/decrypted.ssl.key"

addr = "127.0.0.1"
port = "7050"
)

func getBundleHostnameChecker(hostname string) func(*testing.T, *Bundle) {
return func(t *testing.T, bundle *Bundle) {
if bundle == nil {
Expand Down Expand Up @@ -100,7 +112,7 @@ func TestBundleFromRemote(t *testing.T) {
for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
for _, test := range remoteTests {
b := test.bundlerConstructor(t)
bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
bundle, err := b.BundleFromRemote(test.hostname, test.ip, "443", bf)
if test.errorCallback != nil {
test.errorCallback(t, err)
} else {
Expand All @@ -113,6 +125,38 @@ func TestBundleFromRemote(t *testing.T) {
}
}
}

// Test bundler against a local test server.
cert, err := ioutil.ReadFile(certFile)
if err != nil {
t.Fatal(err.Error())
}
key, err := ioutil.ReadFile(keyFile)
if err != nil {
t.Fatal(err.Error())
}

tlsServer := testsuite.NewTestServer(
http.Server{Addr: net.JoinHostPort(addr, port)})
err = tlsServer.UseDefaultTLSConfig(cert, key)
if err != nil {
t.Fatal(err.Error())
}
err = tlsServer.Start()
if err != nil {
t.Fatal(err.Error())
}

defer tlsServer.Kill()

newBundler, err := NewBundler(certFile, certFile)
if err != nil {
t.Fatal(err.Error())
}
_, err = newBundler.BundleFromRemote("harryharpham.me", addr, port, Optimal)
if err != nil {
t.Fatal(err.Error())
}
}

var remoteSNITests = []remoteTest{
Expand Down Expand Up @@ -152,7 +196,7 @@ func TestBundleFromRemoteSNI(t *testing.T) {
for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
for _, test := range remoteSNITests {
b := test.bundlerConstructor(t)
bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
bundle, err := b.BundleFromRemote(test.hostname, test.ip, "443", bf)
if test.errorCallback != nil {
test.errorCallback(t, err)
} else {
Expand All @@ -172,7 +216,7 @@ func TestBundleFromRemoteFlavor(t *testing.T) {
ubiquity.Platforms = nil
ubiquity.LoadPlatforms(testMetadata)

bundle, err := b.BundleFromRemote(ECCCertSite, "", Ubiquitous)
bundle, err := b.BundleFromRemote(ECCCertSite, "", "443", Ubiquitous)
if err != nil {
t.Errorf("expected no error. but an error occurred: %s", err.Error())
}
Expand All @@ -183,7 +227,7 @@ func TestBundleFromRemoteFlavor(t *testing.T) {
t.Error("expected no untrusted platforms. Got ", bundle.Status.Untrusted)
}

bundle, err = b.BundleFromRemote(ECCCertSite, "", Optimal)
bundle, err = b.BundleFromRemote(ECCCertSite, "", "443", Optimal)
if err != nil {
t.Errorf("expected no error. but an error occurred: %s", err.Error())
}
Expand Down
8 changes: 4 additions & 4 deletions bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ func (b *Bundler) BundleFromPEMorDER(certsRaw, keyPEM []byte, flavor BundleFlavo
// BundleFromRemote fetches the certificate served by the server at
// serverName (or ip, if the ip argument is not the empty string). It
// is expected that the method will be able to make a connection at
// port 443. The certificate used by the server in this connection is
// the input port. The certificate used by the server in this connection is
// used to build the bundle, which will necessarily be keyless.
func (b *Bundler) BundleFromRemote(serverName, ip string, flavor BundleFlavor) (*Bundle, error) {
func (b *Bundler) BundleFromRemote(serverName, ip, port string, flavor BundleFlavor) (*Bundle, error) {
config := &tls.Config{
RootCAs: b.RootPool,
ServerName: serverName,
Expand All @@ -229,9 +229,9 @@ func (b *Bundler) BundleFromRemote(serverName, ip string, flavor BundleFlavor) (
// Dial by IP if present
var dialName string
if ip != "" {
dialName = ip + ":443"
dialName = net.JoinHostPort(ip, port)
} else {
dialName = serverName + ":443"
dialName = net.JoinHostPort(serverName, port)
}

log.Debugf("bundling from remote %s", dialName)
Expand Down
2 changes: 1 addition & 1 deletion bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func TestBundleWithRSAKeyMarshalJSON(t *testing.T) {
// Test marshal to JSON on hostnames
func TestBundleHostnamesMarshalJSON(t *testing.T) {
b := newBundler(t)
bundle, _ := b.BundleFromRemote("www.cloudflare.com", "", Ubiquitous)
bundle, _ := b.BundleFromRemote("www.cloudflare.com", "", "443", Ubiquitous)
hostnames, _ := json.Marshal(bundle.Hostnames)
expectedOne := []byte(`["www.cloudflare.com","cloudflare.com"]`)
expectedTheOther := []byte(`["cloudflare.com","www.cloudflare.com"]`)
Expand Down
70 changes: 70 additions & 0 deletions bundler/testdata/cert/cert_chain.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
-----BEGIN CERTIFICATE-----
MIIGTDCCBTSgAwIBAgIHBTzQSxghazANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UE
BhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBE
aWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENs
YXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMB4XDTE1MDIxODAy
NTcyM1oXDTE2MDIxOTE5NDAzMVowUDELMAkGA1UEBhMCVVMxHzAdBgNVBAMTFnNl
Y3VyZS5oYXJyeWhhcnBoYW0ubWUxIDAeBgkqhkiG9w0BCQEWEWh3aDMzQGNvcm5l
bGwuZWR1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6IWSkznetjqg
0XafBKw56jhIh10JopL2mTpSjhGt3BPNF8nCkUnspzN2CRzwn8owd05NQwX8uPBu
0EWsqTTPKFXR37mS3GpQ/aQhV14vQZbgSG0xex3UYFGVHe3/EE7tTEJzNnJBSYuW
9t7CyJLugRT5Pni++xGUbOnAH9n57ZbtmZ1YEhbw69McumE3rYpwMHFXeMoGGjCj
QzTYF5PRc8IWFaAbQAIvnvQRnmgrj9J763E08T8gaxLocW7S0V8x7WRV93W4AkG4
ieBQM6pcU0ME6lyRDEiL1gEM/GQ6Nb/DljkoquEMmA7PgB1I/EcLDj+BV5B6U6jP
82LCaj0GaQIDAQABo4IC7DCCAugwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYD
VR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFLK8DJjvvpQCcKTg/2Rv7G3aCgnw
MB8GA1UdIwQYMBaAFOtCNNCYsKuf9BtrCPfMZC7vDixFMDIGA1UdEQQrMCmCFnNl
Y3VyZS5oYXJyeWhhcnBoYW0ubWWCD2hhcnJ5aGFycGhhbS5tZTCCAVYGA1UdIASC
AU0wggFJMAgGBmeBDAECATCCATsGCysGAQQBgbU3AQIDMIIBKjAuBggrBgEFBQcC
ARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjCB9wYIKwYBBQUH
AgIwgeowJxYgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwAwIBARqB
vlRoaXMgY2VydGlmaWNhdGUgd2FzIGlzc3VlZCBhY2NvcmRpbmcgdG8gdGhlIENs
YXNzIDEgVmFsaWRhdGlvbiByZXF1aXJlbWVudHMgb2YgdGhlIFN0YXJ0Q29tIENB
IHBvbGljeSwgcmVsaWFuY2Ugb25seSBmb3IgdGhlIGludGVuZGVkIHB1cnBvc2Ug
aW4gY29tcGxpYW5jZSBvZiB0aGUgcmVseWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4w
NQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1j
cmwuY3JsMIGOBggrBgEFBQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2Nz
cC5zdGFydHNzbC5jb20vc3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKG
Nmh0dHA6Ly9haWEuc3RhcnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVy
LmNhLmNydDAjBgNVHRIEHDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJ
KoZIhvcNAQELBQADggEBADVeNvC2WIv3VljSQNS1Kd5M/CyWI1vnAlIDg381EQQF
a1rEgqCF9P7ZBEf+G1+pzt3IhJq2jcxq93RQyWW5cyc+IYQcRaPKK4zC8YWPM12r
p4r9hNTXLOZ4zFclcciPURkZZ8RTw4strq9cnYkt1T4sNR4gBdG0pMHOJt4jJhAj
dCvSmLHXVsUYNld2Tg30Nvq1vi4HaR/Okq5A2bUkD1Gph/2u6op2kapGBXGRRkOn
uYqcKKpIPQT2AtBcQiYoYPjCV/Txlgpdj2JKhVjUwmbIRhob0sBwGMQv45aRkGEi
zOOQAxdW4vOa0VX79s7ePmrnYz0pTfnWtBXC+vajIM0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF2TCCA8GgAwIBAgIHFxU9nqs/vzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQG
EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDE0MjA1NDE3WhcNMjIxMDE0MjA1
NDE3WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
BAMTL1N0YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVy
IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj
0PREGBiEgFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo
/OenJOJApgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn6
6+6CPAVvkvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+v
WjhwRRI/ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxD
KslIDlc5xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21T
Lwb0pwIDAQABo4IBTDCCAUgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
BAMCAQYwHQYDVR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaA
FE4L7xqkQFulF2mHMMo0aEPQQa7yMGkGCCsGAQUFBwEBBF0wWzAnBggrBgEFBQcw
AYYbaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMDAGCCsGAQUFBzAChiRodHRw
Oi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9jYS5jcnQwMgYDVR0fBCswKTAnoCWg
I4YhaHR0cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMEMGA1UdIAQ8MDow
OAYEVR0gADAwMC4GCCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9w
b2xpY3kucGRmMA0GCSqGSIb3DQEBCwUAA4ICAQCBnsOw7dxamNbdJb/ydkh4Qb6E
qgEU+G9hCCIGXwhWRZMYczNJMrpVvyLq5mNOmrFPC7bJrqYV+vEOYHNXrzthLyOG
FFOVQe2cxbmQecFOvbkWVlYAIaTG42sHKVi+RFsG2jRNZcFhHnsFnLPMyE6148lZ
wVdZGsxZvpeHReNUpW0jh7uq90sShFzHs4f7wJ5XmiHOL7fZbnFV6uE/OoFnBWif
CRnd9+RE3uCospESPCRPdbG+Q4GQ+MBS1moXDTRB6DcNoHvqC6eU3r8/Fn/DeA9w
9JHPXUfrAhZYKyOQUIqcfE5bvssaY+oODVxji6BMk8VSVHsJ4FSC1/7Pkt/UPoQp
FVh38wIJnvEUeNVmVl3HHFYTd50irdKYPBC63qi2V/YYI6bJKmbrjfP9Vhyt9uNr
y3Kh4W22ktDuCCvWC7n/gqerdq+VlTRfNt7D/mB0irnaKjEVNCXBXm9V/978J+Ez
8aplGZccQ9jnc9kiPtUp5dj45E3V8vKqzp9srSSI5Xapdg+ZcPY+6HNuVB+MadRp
ZW2One/Qnzg9B4GnVX7MOETImdoP4kXpostFuxoY/5LxCU1LJAIENV4txvT50lX2
GBXCkxllRLWOgdyll11ift/4IO1aCOGDijGIfh498YisM1LGxytmGcxvbJERVri+
gGpWAZ5J6dvtf0s+bA==
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions bundler/testdata/cert/decrypted.ssl.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEA6IWSkznetjqg0XafBKw56jhIh10JopL2mTpSjhGt3BPNF8nC
kUnspzN2CRzwn8owd05NQwX8uPBu0EWsqTTPKFXR37mS3GpQ/aQhV14vQZbgSG0x
ex3UYFGVHe3/EE7tTEJzNnJBSYuW9t7CyJLugRT5Pni++xGUbOnAH9n57ZbtmZ1Y
Ehbw69McumE3rYpwMHFXeMoGGjCjQzTYF5PRc8IWFaAbQAIvnvQRnmgrj9J763E0
8T8gaxLocW7S0V8x7WRV93W4AkG4ieBQM6pcU0ME6lyRDEiL1gEM/GQ6Nb/Dljko
quEMmA7PgB1I/EcLDj+BV5B6U6jP82LCaj0GaQIDAQABAoIBAQDOIryS8NbUTp2L
lNHc3qJpVoRWHNER45/ir6XIdTvgw10rHZ70FslKYYDfC1z3C9RzsGMmbARkICLd
WSd8ymhspchtwqLD7Szn773vKnxSdWNYUhVvxD4nNaww4HEjEBWnabGiLyBaBvpK
2altD3WJ0gI0s+77vdYLyB6fHitHyLk7yd12cpv8Q85VE+aZFNbVsaDLli/h+afT
0b9pRcF4J5k+Rk4UO9ZxQ99Zxi2cwA+AU1hoZYH2E0ti7hJD/577qNZ07aIiGO65
2i7y28QKpQT0Pcc1dhVVMVYX7i0uUNCu+lsK0GO5A7amAYbm+cDF+NMUlWXx2hFz
R32lKOXRAoGBAPRdHEB9OdD+5UNGIAT66IWUC2NZIT2bhAyJrdlrmHIP/RYFzUom
k9hjoVpDtWey5NzFDmVIFlp2LMHM/sxOYNra9ddR6YMiJtmq3OMwXJjcFjKOzq/s
xA2Tag9b9Ds4vzcAgVLcaO1fGzNOupP1ETUI+aRdpiIkL9we11xnMfmrAoGBAPOY
Gq/FJ8XHmckPJim9dOKvrX/P9uqLkZjnWEZfrdjDYRjH+CB84RV8hk0fWVJvQmnV
USpgblPxmQA143Zm/z5UePRa1fhscAepBlARg9dacSee6/aBXVqXOtn72yZcIca6
25ZDlqMMt0OsdWuwcMrCc0cSPEngnn8PY7iUxXQ7AoGBAL9xcwDTGsix6cua1NsR
97kvEvzyhyhM/lcURi9gLD6waAco5HyDXLDa3T5qbWSgssyDVZPjth+JFed/Qt+t
SBQuFwxqEBe8WdOOGR+kc+cOBhX169fIFpDMPPtrfxwmiSf+LVNNeqb9K8I2m9Xu
2VxDe9FZzR5SW2yIfRDXiD+hAoGBALCoFnJyYK2mW3jca6jJpQLgtMqEX2UpYqWo
4PPoX4Nb7gayvteQuQuEC0HTAkwuM9Pcx8gbtudZxsPIUPWFLIZfbHiJh7NpsLVd
dx6KFTsQdA9vyWAz4SfZlOyRIhVnq3cb/DO1QIFur1l8sIswohvpeQCJ0P8izs8G
siMigTARAoGBANSp96QqJ7gNYzHN18GhBwwkCOBE4HC1GkTGlROmZG3M0N9+j7WI
MTBjf0VS9V+aRqqvIFGTv3kpk6Wp0fxyXGL8vFK3DoyrGeWr3URXlHYiAyjfa3dr
URXCnqHcaMDfgzrBZf4Hi2sTsZYximWv/v+YUGStwbWcgwJ9Eep2gixp
-----END RSA PRIVATE KEY-----
2 changes: 1 addition & 1 deletion cli/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func bundlerMain(args []string, c cli.Config) (err error) {
}
}
} else if c.Domain != "" {
bundle, err = b.BundleFromRemote(c.Domain, c.IP, flavor)
bundle, err = b.BundleFromRemote(c.Domain, c.IP, "443", flavor)
if err != nil {
return
}
Expand Down
130 changes: 130 additions & 0 deletions helpers/testsuite/certificates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Functions which allow for the creation of dummy certificates, chains, and
// keys from certificate requests.

package testsuite

import (
"reflect"
"time"

"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/initca"
"github.com/cloudflare/cfssl/signer"
"github.com/cloudflare/cfssl/signer/local"
)

// CreateCertificateChain creates a chain of certificates from a slice of
// requests. The first request is the root certificate and the last is the
// leaf. The chain is returned as a slice of PEM-encoded bytes.
func CreateCertificateChain(requests []csr.CertificateRequest,
options SignOptions) (certChain []byte, key []byte, err error) {

// Create the root certificate using the first request. This will be
// self-signed.
certChain = make([]byte, 0)
rootCert, _, prevKey, err := initca.New(&requests[0])
if err != nil {
return nil, nil, err
}
certChain = append(certChain, rootCert...)

// For each of the next requests, create a certificate signed by the
// previous certificate.
prevCert := rootCert
for _, request := range requests[1:] {
cert, key, err := SignCertificate(request, prevCert, prevKey, options)
if err != nil {
return nil, nil, err
}
certChain = append(certChain, byte('\n'))
certChain = append(certChain, cert...)
prevCert = cert
prevKey = key
}

return certChain, key, nil
}

// SignOptions allows callers to configure the signer according to their needs
// when calling SignCertificate. Any of these can be left nil, in which case
// standard defaults will be used.
type SignOptions struct {
Hosts []string
Profile config.SigningProfile
Label string
SerialSeq string
WhiteList signer.Whitelist
}

// SignCertificate takes a request and a certificate / key combination. A new
// certificate and key are generated from the request and signed by the input
// certificate. The 'options' argument allows the internal signer to be
// configured as needed. The returned certificate and key are PEM-encoded bytes.
func SignCertificate(request csr.CertificateRequest, signerCert, signerKey []byte,
options SignOptions) (encodedCert, encodedKey []byte, err error) {

// The default profile (used when options.Profile is not set).
// Allows the signed certificate can be used as intermediate CA and server
// auth certificate.
defaultProfile := config.SigningProfile{
Usage: []string{"cert sign", "server auth"},
CA: true,
Expiry: time.Hour,
ExpiryString: "1h",
}

// If options.Profile is the zero value, replace it with the default profile.
emptyProfile := config.SigningProfile{}
if reflect.DeepEqual(options.Profile, emptyProfile) {
options.Profile = defaultProfile
}

// Generate the signer using the certificate, key, and profile.
policy := &config.Signing{
Profiles: map[string]*config.SigningProfile{},
Default: &options.Profile,
}
priv, err := helpers.ParsePrivateKeyPEM(signerKey)
if err != nil {
return nil, nil, err
}
parsedSignerCert, err := helpers.ParseCertificatePEM(signerCert)
if err != nil {
return nil, nil, err
}
sigAlgo := signer.DefaultSigAlgo(priv)
localSigner, err := local.NewSigner(priv, parsedSignerCert, sigAlgo, policy)
if err != nil {
return nil, nil, err
}

// Get the CSR bytes and key bytes for the request. Store the CSR bytes in
// a temporary file.
csrBytes, encodedKey, err := csr.ParseRequest(&request)
if err != nil {
return nil, nil, err
}

// Construct the subject from the request and options.WhiteList.
subject := &signer.Subject{
CN: request.CN,
Names: request.Names,
Whitelist: &options.WhiteList,
}

// Create a sign request.
// Note: we do not need to set a profile as the signer will use the default
// we already set.
signReq := signer.SignRequest{
Hosts: options.Hosts,
Request: string(csrBytes),
Subject: subject,
Label: options.Label,
SerialSeq: options.SerialSeq,
}

encodedCert, err = localSigner.Sign(signReq)
return
}
Loading