func (b *backend) pathSetSignedIntermediate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { cert := data.Get("certificate").(string) if cert == "" { return logical.ErrorResponse("no certificate provided in the \"certficate\" parameter"), nil } inputBundle, err := certutil.ParsePEMBundle(cert) if err != nil { switch err.(type) { case certutil.InternalError: return nil, err default: return logical.ErrorResponse(err.Error()), nil } } // If only one certificate is provided and it's a CA // the parsing will assign it to the IssuingCA, so move it over if inputBundle.Certificate == nil && inputBundle.IssuingCA != nil { inputBundle.Certificate = inputBundle.IssuingCA inputBundle.IssuingCA = nil inputBundle.CertificateBytes = inputBundle.IssuingCABytes inputBundle.IssuingCABytes = nil } if inputBundle.Certificate == nil { return logical.ErrorResponse("supplied certificate could not be successfully parsed"), nil } cb := &certutil.CertBundle{} entry, err := req.Storage.Get("config/ca_bundle") if err != nil { return nil, err } if entry == nil { return logical.ErrorResponse("could not find any existing entry with a private key"), nil } err = entry.DecodeJSON(cb) if err != nil { return nil, err } if len(cb.PrivateKey) == 0 || cb.PrivateKeyType == "" { return logical.ErrorResponse("could not find an existing private key"), nil } parsedCB, err := cb.ToParsedCertBundle() if err != nil { return nil, err } if parsedCB.PrivateKey == nil { return nil, fmt.Errorf("saved key could not be parsed successfully") } equal, err := certutil.ComparePublicKeys(parsedCB.PrivateKey.Public(), inputBundle.Certificate.PublicKey) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "error matching public keys: %v", err)), nil } if !equal { return logical.ErrorResponse("key in certificate does not match stored key"), nil } inputBundle.PrivateKey = parsedCB.PrivateKey inputBundle.PrivateKeyType = parsedCB.PrivateKeyType inputBundle.PrivateKeyBytes = parsedCB.PrivateKeyBytes if !inputBundle.Certificate.IsCA { return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil } cb, err = inputBundle.ToCertBundle() if err != nil { return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err) } entry, err = logical.StorageEntryJSON("config/ca_bundle", cb) if err != nil { return nil, err } err = req.Storage.Put(entry) if err != nil { return nil, err } entry.Key = "certs/" + cb.SerialNumber entry.Value = inputBundle.CertificateBytes err = req.Storage.Put(entry) if err != nil { return nil, err } // For ease of later use, also store just the certificate at a known // location entry.Key = "ca" entry.Value = inputBundle.CertificateBytes err = req.Storage.Put(entry) if err != nil { return nil, err } // Build a fresh CRL err = buildCRL(b, req) return nil, err }
func (b *backend) pathCAWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { pemBundle := data.Get("pem_bundle").(string) parsedBundle, err := certutil.ParsePEMBundle(pemBundle) if err != nil { switch err.(type) { case certutil.InternalError: return nil, err default: return logical.ErrorResponse(err.Error()), nil } } if parsedBundle.PrivateKey == nil || parsedBundle.PrivateKeyType == certutil.UnknownPrivateKey { return logical.ErrorResponse("private key not found in the PEM bundle"), nil } // Handle the case of a self-signed certificate; the parsing function will // see the CA and put it into the issuer if parsedBundle.Certificate == nil && parsedBundle.IssuingCA != nil { equal, err := certutil.ComparePublicKeys(parsedBundle.IssuingCA.PublicKey, parsedBundle.PrivateKey.Public()) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "got only a CA and private key but could not verify the public keys match: %v", err)), nil } if !equal { return logical.ErrorResponse( "got only a CA and private key but keys do not match"), nil } parsedBundle.Certificate = parsedBundle.IssuingCA parsedBundle.CertificateBytes = parsedBundle.IssuingCABytes } if parsedBundle.Certificate == nil { return logical.ErrorResponse("no certificate found in the PEM bundle"), nil } if !parsedBundle.Certificate.IsCA { return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil } cb, err := parsedBundle.ToCertBundle() if err != nil { return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err) } entry, err := logical.StorageEntryJSON("config/ca_bundle", cb) if err != nil { return nil, err } err = req.Storage.Put(entry) if err != nil { return nil, err } // For ease of later use, also store just the certificate at a known // location, plus a fresh CRL entry.Key = "ca" entry.Value = parsedBundle.CertificateBytes err = req.Storage.Put(entry) if err != nil { return nil, err } err = buildCRL(b, req) return nil, err }