diff --git a/cmd/fabric-ca-server/config.go b/cmd/fabric-ca-server/config.go index 215c75685..3fee8e041 100644 --- a/cmd/fabric-ca-server/config.go +++ b/cmd/fabric-ca-server/config.go @@ -21,7 +21,6 @@ import ( "fmt" "io/ioutil" "os" - "path" "path/filepath" "strings" @@ -124,15 +123,16 @@ registry: maxEnrollments: 0 # Contains user information which is used when LDAP is disabled - user: - <<>>: + identities: + - name: <<>> pass: <<>> type: client - affiliation: org1.department1 + affiliation: "" attrs: hf.Registrar.Roles: "client,user,peer,validator,auditor,ca" hf.Registrar.DelegateRoles: "client,user,validator,auditor" hf.Revoker: true + hf.IntermediateCA: true ############################################################################# # Database section @@ -189,6 +189,12 @@ affiliations: ############################################################################# signing: profiles: + ca: + usage: + - cert sign + expiry: 8000h + caconstraint: + isca: true default: usage: - cert sign @@ -270,26 +276,12 @@ func configInit() (err error) { return nil } -// Get the default path for the config file to display in usage message -func getDefaultConfigFile() (string, error) { - var fname = fmt.Sprintf("%s-config.yaml", cmdName) - // First check home env variables - home := os.Getenv("FABRIC_CA_SERVER_HOME") - if home == "" { - home = os.Getenv("CA_CFG_PATH") - } - if home != "" { - return path.Join(home, fname), nil - } - return fname, nil -} - func createDefaultConfigFile() error { - // Create a default config, but only if they provided a - // bootstrap user ID and password + // Create a default config, but only if they provided an administrative + // user ID and password up := viper.GetString("boot") if up == "" { - return fmt.Errorf("The '-b user:pass' option is required; see '%s init -h'", cmdName) + return errors.New("The '-b user:pass' option is required") } ups := strings.Split(up, ":") if len(ups) < 2 { @@ -316,7 +308,7 @@ func createDefaultConfigFile() error { cfg = strings.Replace(cfg, "<<>>", pass, 1) cfg = strings.Replace(cfg, "<<>>", myhost, 1) // Now write the file - err = os.MkdirAll(filepath.Dir(cfgFileName), 0644) + err = os.MkdirAll(filepath.Dir(cfgFileName), 0755) if err != nil { return err } diff --git a/cmd/fabric-ca-server/init.go b/cmd/fabric-ca-server/init.go index 33391ae1b..7b08cf59a 100644 --- a/cmd/fabric-ca-server/init.go +++ b/cmd/fabric-ca-server/init.go @@ -18,11 +18,9 @@ package main import ( "fmt" - "path/filepath" "github.com/cloudflare/cfssl/csr" "github.com/cloudflare/cfssl/log" - "github.com/hyperledger/fabric-ca/lib" "github.com/hyperledger/fabric-ca/util" "github.com/spf13/cobra" ) @@ -51,11 +49,7 @@ func runInit(cmd *cobra.Command, args []string) error { if len(args) > 0 { return fmt.Errorf("Usage: too many arguments.\n%s", initCmd.UsageString()) } - server := lib.Server{ - HomeDir: filepath.Dir(cfgFileName), - Config: serverCfg, - } - err := server.Init(false) + err := getServer().Init(false) if err != nil { util.Fatal("Initialization failure: %s", err) } diff --git a/cmd/fabric-ca-server/main.go b/cmd/fabric-ca-server/main.go index 1137005b0..12a69e307 100644 --- a/cmd/fabric-ca-server/main.go +++ b/cmd/fabric-ca-server/main.go @@ -18,6 +18,7 @@ package main import ( "os" + "path/filepath" "strings" "github.com/hyperledger/fabric-ca/lib" @@ -57,7 +58,7 @@ func init() { pflags.StringVarP(&cfgFileName, "config", "c", cfg, "Configuration file") util.FlagString(pflags, "url", "u", "", "URL of the parent fabric-ca-server") util.FlagString(pflags, "boot", "b", "", - "The user:pass for bootstrap admin (required to build default config file") + "The user:pass for bootstrap admin which is required to build default config file") // Register flags for all tagged and exported fields in the config serverCfg = &lib.ServerConfig{} @@ -104,3 +105,13 @@ func registerCommonFlags(flags *pflag.FlagSet) { util.FlagString(flags, "tls.certfile", "", "cert.pem", "PEM-encoded certificate file used for TLS") } + +// Get a server for the init and start commands +func getServer() *lib.Server { + return &lib.Server{ + HomeDir: filepath.Dir(cfgFileName), + Config: serverCfg, + BlockingStart: blockingStart, + ParentServerURL: viper.GetString("url"), + } +} diff --git a/cmd/fabric-ca-server/main_test.go b/cmd/fabric-ca-server/main_test.go index e80e18824..c45078497 100644 --- a/cmd/fabric-ca-server/main_test.go +++ b/cmd/fabric-ca-server/main_test.go @@ -20,6 +20,8 @@ import ( "fmt" "os" "testing" + + "github.com/hyperledger/fabric-ca/util" ) const ( @@ -78,7 +80,7 @@ func TestBogus(t *testing.T) { } func TestClean(t *testing.T) { - defYaml, _ := getDefaultConfigFile() + defYaml := util.GetDefaultConfigFile(cmdName) os.Remove(defYaml) os.Remove(testYaml) os.Remove("ca-key.pem") diff --git a/cmd/fabric-ca-server/start.go b/cmd/fabric-ca-server/start.go index e8c95cd28..635a9d1be 100644 --- a/cmd/fabric-ca-server/start.go +++ b/cmd/fabric-ca-server/start.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "path/filepath" "github.com/hyperledger/fabric-ca/lib" "github.com/hyperledger/fabric-ca/util" @@ -45,12 +44,7 @@ func runStart(cmd *cobra.Command, args []string) error { if len(args) > 0 { return fmt.Errorf("Usage: too many arguments.\n%s", startCmd.UsageString()) } - server := lib.Server{ - HomeDir: filepath.Dir(cfgFileName), - Config: serverCfg, - BlockingStart: blockingStart, - } - err := server.Start() + err := getServer().Start() if err != nil { return err } diff --git a/lib/clientconfig.go b/lib/clientconfig.go index 2ebce650c..5df638f8b 100644 --- a/lib/clientconfig.go +++ b/lib/clientconfig.go @@ -16,10 +16,37 @@ limitations under the License. package lib -import "github.com/hyperledger/fabric-ca/lib/tls" +import ( + "net/url" + + "github.com/hyperledger/fabric-ca/api" + "github.com/hyperledger/fabric-ca/lib/tls" +) // ClientConfig is the fabric-ca client's config type ClientConfig struct { - URL string `mapstructure:"url"` - TLS tls.ClientTLSConfig `mapstructure:"tls"` + URL string `yaml:"url,omitempty"` + TLS tls.ClientTLSConfig `yaml:"tls,omitempty"` + Enrollment api.EnrollmentRequest `yaml:"enrollment,omitempty"` +} + +// Enroll a client given the server's URL and the client's home directory. +// The URL may be of the form: http://user:pass@host:port where user and pass +// are the enrollment ID and secret, respectively. +func (c *ClientConfig) Enroll(rawurl, home string) (id *Identity, err error) { + purl, err := url.Parse(rawurl) + if err != nil { + return nil, err + } + if purl.User != nil { + name := purl.User.Username() + secret, _ := purl.User.Password() + c.Enrollment.Name = name + c.Enrollment.Secret = secret + purl.User = nil + } + c.URL = purl.String() + c.TLS.Enabled = purl.Scheme == "https" + client := &Client{HomeDir: home, Config: c} + return client.Enroll(&c.Enrollment) } diff --git a/lib/server.go b/lib/server.go index a51d6c876..fbdde40ff 100644 --- a/lib/server.go +++ b/lib/server.go @@ -28,7 +28,7 @@ import ( "strconv" "github.com/cloudflare/cfssl/config" - "github.com/cloudflare/cfssl/csr" + cfcsr "github.com/cloudflare/cfssl/csr" "github.com/cloudflare/cfssl/initca" "github.com/cloudflare/cfssl/log" "github.com/cloudflare/cfssl/signer" @@ -70,6 +70,8 @@ type Server struct { BlockingStart bool // The server's configuration Config *ServerConfig + // The parent server URL, which is non-null if this is an intermediate server + ParentServerURL string // The database handle used to store certificates and optionally // the user registry information, unless LDAP it enabled for the // user registry function. @@ -186,22 +188,10 @@ func (s *Server) initKeyMaterial(renew bool) error { } } - // Create the certificate request, copying from config - ptr := &s.Config.CSR - req := csr.CertificateRequest{ - CN: ptr.CN, - Names: ptr.Names, - Hosts: ptr.Hosts, - // FIXME: NewBasicKeyRequest only does ecdsa 256; use config - KeyRequest: csr.NewBasicKeyRequest(), - CA: ptr.CA, - SerialNumber: ptr.SerialNumber, - } - - // Initialize the CA now - cert, _, key, err := initca.New(&req) + // Get the CA cert and key + cert, key, err := s.getCACertAndKey() if err != nil { - return fmt.Errorf("Failed to initialize CA [%s]\nRequest was %#v", err, req) + return fmt.Errorf("Failed to initialize CA: %s", err) } // Store the key and certificate to file @@ -219,6 +209,58 @@ func (s *Server) initKeyMaterial(renew bool) error { return nil } +// Get the CA certificate and key for this server +func (s *Server) getCACertAndKey() (cert, key []byte, err error) { + log.Debugf("Getting CA cert and key; parent server URL is '%s'", s.ParentServerURL) + if s.ParentServerURL != "" { + // This is an intermediate CA, so call the parent fabric-ca-server + // to get the key and cert + clientCfg := s.Config.Client + if clientCfg == nil { + clientCfg = &ClientConfig{} + } + if clientCfg.Enrollment.Profile == "" { + clientCfg.Enrollment.Profile = "ca" + } + if clientCfg.Enrollment.CSR == nil { + clientCfg.Enrollment.CSR = &api.CSRInfo{} + } + if clientCfg.Enrollment.CSR.CA == nil { + clientCfg.Enrollment.CSR.CA = &cfcsr.CAConfig{PathLength: 0, PathLenZero: true} + } + log.Debugf("Intermediate enrollment request: %v", clientCfg.Enrollment) + var id *Identity + id, err = clientCfg.Enroll(s.ParentServerURL, s.HomeDir) + if err != nil { + return nil, nil, err + } + ecert := id.GetECert() + if ecert == nil { + return nil, nil, errors.New("No ECert from parent server") + } + cert = ecert.Cert() + key = ecert.Key() + } else { + // This is a root CA, so call cfssl to get the key and cert. + csr := &s.Config.CSR + req := cfcsr.CertificateRequest{ + CN: csr.CN, + Names: csr.Names, + Hosts: csr.Hosts, + // FIXME: NewBasicKeyRequest only does ecdsa 256; use config + KeyRequest: cfcsr.NewBasicKeyRequest(), + CA: csr.CA, + SerialNumber: csr.SerialNumber, + } + // Call CFSSL to initialize the CA + cert, _, key, err = initca.New(&req) + } + if err != nil { + return nil, nil, err + } + return cert, key, nil +} + // RegisterBootstrapUser registers the bootstrap user with appropriate privileges func (s *Server) RegisterBootstrapUser(user, pass, affiliation string) error { // Initialize the config, setting defaults, etc @@ -230,14 +272,15 @@ func (s *Server) RegisterBootstrapUser(user, pass, affiliation string) error { return fmt.Errorf("Failed to register bootstrap user '%s': %s", user, err) } id := ServerConfigIdentity{ - ID: user, + Name: user, Pass: pass, Type: "user", Affiliation: affiliation, - Attributes: map[string]string{ + Attrs: map[string]string{ "hf.Registrar.Roles": "client,user,peer,validator,auditor", "hf.Registrar.DelegateRoles": "client,user,validator,auditor", "hf.Revoker": "true", + "hf.IntermediateCA": "true", }, } registry := &s.Config.Registry @@ -387,6 +430,7 @@ func (s *Server) initEnrollmentSigner() (err error) { Profiles: map[string]*config.SigningProfile{}, Default: config.DefaultConfig(), } + policy.Default.CAConstraint.IsCA = true } // Make sure the policy reflects the new remote @@ -518,7 +562,7 @@ func (s *Server) loadUsersTable() error { log.Debug("Loading users table") registry := &s.Config.Registry for _, id := range registry.Identities { - log.Debugf("Loading identity '%s'", id.ID) + log.Debugf("Loading identity '%s'", id.Name) err := s.addIdentity(&id, false) if err != nil { return err @@ -535,7 +579,8 @@ func (s *Server) loadAffiliationsTable() error { if err == nil { log.Debug("Successfully loaded affiliations table") } - return err + log.Debug("Successfully loaded groups table") + return nil } // Recursive function to load the affiliations table hierarchy @@ -583,10 +628,10 @@ func (s *Server) loadAffiliationsTableR(val interface{}, parentPath string) (err // Add an identity to the registry func (s *Server) addIdentity(id *ServerConfigIdentity, errIfFound bool) error { - user, _ := s.registry.GetUser(id.ID, nil) + user, _ := s.registry.GetUser(id.Name, nil) if user != nil { if errIfFound { - return fmt.Errorf("Identity '%s' is already registered", id.ID) + return fmt.Errorf("Identity '%s' is already registered", id.Name) } log.Debugf("Loaded identity: %+v", id) return nil @@ -596,16 +641,16 @@ func (s *Server) addIdentity(id *ServerConfigIdentity, errIfFound bool) error { return err } rec := spi.UserInfo{ - Name: id.ID, + Name: id.Name, Pass: id.Pass, Type: id.Type, Group: id.Affiliation, - Attributes: s.convertAttrs(id.Attributes), + Attributes: s.convertAttrs(id.Attrs), MaxEnrollments: maxEnrollments, } err = s.registry.InsertUser(rec) if err != nil { - return fmt.Errorf("Failed to insert user '%s': %s", id.ID, err) + return fmt.Errorf("Failed to insert user '%s': %s", id.Name, err) } log.Debugf("Registered identity: %+v", id) return nil @@ -667,7 +712,7 @@ func (s *Server) makeFileNamesAbsolute() error { } func writeFile(file string, buf []byte, perm os.FileMode) error { - err := os.MkdirAll(filepath.Dir(file), perm) + err := os.MkdirAll(filepath.Dir(file), 0755) if err != nil { return err } diff --git a/lib/server_test.go b/lib/server_test.go index f7b37bc99..60a2c0fb6 100644 --- a/lib/server_test.go +++ b/lib/server_test.go @@ -19,22 +19,24 @@ package lib_test import ( "fmt" "os" + "path" + "strconv" "testing" + "time" "github.com/hyperledger/fabric-ca/api" "github.com/hyperledger/fabric-ca/lib" ) const ( - port = 7055 + rootPort = 7055 + rootDir = "rootDir" + intermediatePort = 7056 + intermediateDir = "intDir" ) -func TestBegin(t *testing.T) { - clean() -} - func TestServerInit(t *testing.T) { - server := getServer(t) + server := getRootServer(t) if server == nil { return } @@ -52,14 +54,14 @@ func TestServerInit(t *testing.T) { } } -func TestRunningServer(t *testing.T) { +func TestRootServer(t *testing.T) { var err error var admin, user1 *lib.Identity var rr *api.RegistrationResponse var recs []lib.CertRecord // Start the server - server := getServer(t) + server := getRootServer(t) if server == nil { return } @@ -67,14 +69,14 @@ func TestRunningServer(t *testing.T) { if err != nil { t.Fatalf("Server start failed: %s", err) } + defer server.Stop() // Enroll request - client := getTestClient() + client := getRootClient() admin, err = client.Enroll(&api.EnrollmentRequest{ Name: "admin", Secret: "adminpw", }) if err != nil { - server.Stop() t.Fatalf("Failed to enroll admin/adminpw: %s", err) } // Register user1 @@ -84,7 +86,6 @@ func TestRunningServer(t *testing.T) { Group: "hyperledger.fabric.security", }) if err != nil { - server.Stop() t.Fatalf("Failed to register user1: %s", err) } // Enroll user1 @@ -93,7 +94,6 @@ func TestRunningServer(t *testing.T) { Secret: rr.Secret, }) if err != nil { - server.Stop() t.Fatalf("Failed to enroll user1: %s", err) } // The admin ID should have 1 cert in the DB now @@ -126,13 +126,11 @@ func TestRunningServer(t *testing.T) { // User1 get's batch of tcerts _, err = user1.GetTCertBatch(&api.GetTCertBatchRequest{Count: 1}) if err != nil { - server.Stop() t.Fatalf("Failed to get tcerts for user1: %s", err) } // Revoke user1's identity err = admin.Revoke(&api.RevocationRequest{Name: "user1"}) if err != nil { - server.Stop() t.Fatalf("Failed to revoke user1's identity: %s", err) } // User1 should not be allowed to get tcerts now that it is revoked @@ -149,32 +147,90 @@ func TestRunningServer(t *testing.T) { } } -func TestEnd(t *testing.T) { - clean() +func TestIntermediateServer(t *testing.T) { + var err error + + // Start the root server + rootServer := getRootServer(t) + if rootServer == nil { + return + } + err = rootServer.Start() + if err != nil { + t.Fatalf("Root server start failed: %s", err) + } + defer rootServer.Stop() + + for idx := 0; idx < 3; idx++ { + testIntermediateServer(idx, t) + } + + // Stop both servers + err = rootServer.Stop() + if err != nil { + t.Errorf("Root server stop failed: %s", err) + } } -func clean() { - var files = []string{"key.pem", "cert.pem", "ca-key.pem", "ca-cert.pem", "fabric-ca-server.db"} - for _, file := range files { - os.Remove(file) +func testIntermediateServer(idx int, t *testing.T) { + // Init the intermediate server + intermediateServer := getIntermediateServer(idx, t) + if intermediateServer == nil { + return + } + err := intermediateServer.Init(true) + if err != nil { + t.Fatalf("Intermediate server init failed: %s", err) + } + // Start it + err = intermediateServer.Start() + if err != nil { + t.Fatalf("Intermediate server start failed: %s", err) } + time.Sleep(time.Second) + // Stop it + intermediateServer.Stop() +} + +func TestEnd(t *testing.T) { + os.RemoveAll(rootDir) + os.RemoveAll(intermediateDir) +} + +func getRootServerURL() string { + return fmt.Sprintf("http://admin:adminpw@localhost:%d", rootPort) } -func getServer(t *testing.T) *lib.Server { +func getRootServer(t *testing.T) *lib.Server { + return getServer(rootPort, rootDir, "", t) +} + +func getIntermediateServer(idx int, t *testing.T) *lib.Server { + return getServer( + intermediatePort, + path.Join(intermediateDir, strconv.Itoa(idx)), + getRootServerURL(), + t) +} + +func getServer(port int, home, parentURL string, t *testing.T) *lib.Server { + os.RemoveAll(home) affiliations := map[string]interface{}{ "hyperledger": map[string]interface{}{ "fabric": []string{"ledger", "orderer", "security"}, "fabric-ca": nil, "sdk": nil, }, - "sawtooth": nil, + "org2": nil, } srv := &lib.Server{ Config: &lib.ServerConfig{ - Port: 7055, + Port: port, Debug: true, Affiliations: affiliations, }, + HomeDir: home, + ParentServerURL: parentURL, } // The bootstrap user's affiliation is the empty string, which // means the user is at the affiliation root @@ -186,7 +242,15 @@ func getServer(t *testing.T) *lib.Server { return srv } -func getTestClient() *lib.Client { +func getRootClient() *lib.Client { + return getTestClient(rootPort) +} + +func getIntermediateClient() *lib.Client { + return getTestClient(intermediatePort) +} + +func getTestClient(port int) *lib.Client { return &lib.Client{ Config: &lib.ClientConfig{URL: fmt.Sprintf("http://localhost:%d", port)}, HomeDir: "../testdata", diff --git a/lib/serverconfig.go b/lib/serverconfig.go index ee0dd0b65..d906810d7 100644 --- a/lib/serverconfig.go +++ b/lib/serverconfig.go @@ -77,10 +77,10 @@ type ServerConfigRegistry struct { // ServerConfigIdentity is identity information in the server's config type ServerConfigIdentity struct { - ID string + Name string Pass string Type string Affiliation string MaxEnrollments int - Attributes map[string]string + Attrs map[string]string } diff --git a/lib/serverenroll.go b/lib/serverenroll.go index a0afcf63a..ee8b257da 100644 --- a/lib/serverenroll.go +++ b/lib/serverenroll.go @@ -17,16 +17,27 @@ limitations under the License. package lib import ( + "crypto/x509" + "encoding/asn1" + "encoding/pem" + "errors" "fmt" "io/ioutil" "net/http" - cfsslapi "github.com/cloudflare/cfssl/api" + cfapi "github.com/cloudflare/cfssl/api" + "github.com/cloudflare/cfssl/csr" + cferr "github.com/cloudflare/cfssl/errors" "github.com/cloudflare/cfssl/log" "github.com/cloudflare/cfssl/signer" "github.com/hyperledger/fabric-ca/util" ) +var ( + // The X.509 BasicConstraints object identifier (RFC 5280, 4.2.1.9) + basicConstraintsOID = asn1.ObjectIdentifier{2, 5, 29, 19} +) + // NewEnrollHandler is the constructor for the enroll handler func NewEnrollHandler() (h http.Handler, err error) { return newSignHandler("enroll") @@ -46,7 +57,7 @@ type signHandler struct { // newEnrollHandler is the constructor for an enroll or reenroll handler func newSignHandler(endpoint string) (h http.Handler, err error) { // NewHandler is constructor for register handler - return &cfsslapi.HTTPHandler{ + return &cfapi.HTTPHandler{ Handler: &signHandler{endpoint: endpoint}, Methods: []string{"POST"}, }, nil @@ -73,6 +84,13 @@ func (sh *signHandler) Handle(w http.ResponseWriter, r *http.Request) error { return err } + // Make any authorization checks needed, depending on the contents + // of the CSR (Certificate Signing Request) + err = csrAuthCheck(&req, r) + if err != nil { + return err + } + cert, err := EnrollSigner.Sign(req) if err != nil { err = fmt.Errorf("Failed signing for endpoint %s: %s", sh.endpoint, err) @@ -80,5 +98,45 @@ func (sh *signHandler) Handle(w http.ResponseWriter, r *http.Request) error { return err } - return cfsslapi.SendResponse(w, cert) + return cfapi.SendResponse(w, cert) +} + +// Make any authorization checks needed, depending on the contents +// of the CSR (Certificate Signing Request). +// In particular, if the request is for an intermediate CA certificate, +// the caller must have the "hf.IntermediateCA" attribute. +func csrAuthCheck(req *signer.SignRequest, r *http.Request) error { + // Decode and parse the request into a CSR so we can make checks + block, _ := pem.Decode([]byte(req.Request)) + if block == nil { + return cferr.New(cferr.CSRError, cferr.DecodeFailed) + } + if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" { + return cferr.Wrap(cferr.CSRError, + cferr.BadRequest, errors.New("not a certificate or csr")) + } + csrReq, err := x509.ParseCertificateRequest(block.Bytes) + if err != nil { + return err + } + // Check the CSR for the X.509 BasicConstraints extension (RFC 5280, 4.2.1.9) + for _, val := range csrReq.Extensions { + if val.Id.Equal(basicConstraintsOID) { + var constraints csr.BasicConstraints + var rest []byte + if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil { + return cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err) + } else if len(rest) != 0 { + return cferr.Wrap(cferr.CSRError, cferr.ParseFailed, errors.New("x509: trailing data after X.509 BasicConstraints")) + } + if constraints.IsCA { + log.Debug("CSR request received for an intermediate CA") + // This is a request for a CA certificate, so make sure the caller + // has the 'hf.IntermediateCA' attribute + return userHasAttribute(r.Header.Get(enrollmentIDHdrName), "hf.IntermediateCA") + } + } + } + log.Debug("CSR request received") + return nil } diff --git a/lib/serverregister.go b/lib/serverregister.go index e24a4bcda..f27410165 100644 --- a/lib/serverregister.go +++ b/lib/serverregister.go @@ -63,12 +63,12 @@ func (h *registerHandler) Handle(w http.ResponseWriter, r *http.Request) error { // Register User callerID := r.Header.Get(enrollmentIDHdrName) - tok, err := h.RegisterUser(req.Name, req.Type, req.Group, req.Attributes, callerID) + secret, err := h.RegisterUser(req.Name, req.Type, req.Group, req.Attributes, callerID) if err != nil { return err } - resp := &api.RegistrationResponseNet{RegistrationResponse: api.RegistrationResponse{Secret: string(tok)}} + resp := &api.RegistrationResponseNet{RegistrationResponse: api.RegistrationResponse{Secret: secret}} log.Debugf("Registration completed - sending response %+v", resp) return cfsslapi.SendResponse(w, resp) diff --git a/lib/signer.go b/lib/signer.go index 2c107da13..ab2f9b5d0 100644 --- a/lib/signer.go +++ b/lib/signer.go @@ -40,6 +40,16 @@ type Signer struct { client *Client } +// Key returns the key bytes of this signer +func (s *Signer) Key() []byte { + return s.key +} + +// Cert returns the cert bytes of this signer +func (s *Signer) Cert() []byte { + return s.cert +} + // RevokeSelf revokes only the certificate associated with this signer func (s *Signer) RevokeSelf() error { log.Debugf("RevokeSelf %s", s.name)