wip: make order submission work

This commit is contained in:
Julien Vehent 2017-05-22 21:24:19 -04:00
Родитель 8d08731b0f
Коммит 6190c2cb00
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A3D652173B763E8F
5 изменённых файлов: 100 добавлений и 21 удалений

Просмотреть файл

@ -3,6 +3,7 @@ package main
import (
"crypto/x509"
"flag"
"fmt"
"log"
"os"
@ -10,6 +11,7 @@ import (
)
var (
debug = flag.Bool("D", false, "Enable debug output")
host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
ou = flag.String("ou", "Cloud Services", "Organizational Unit")
org = flag.String("org", "Mozilla Corporation", "Organization")
@ -32,18 +34,27 @@ func main() {
if err != nil {
log.Fatal(err)
}
if *debug {
cli.EnableDebug()
}
_, err = cli.ViewProductList()
if err != nil {
log.Fatal(err)
}
// Step 1: make a certificate request and a private key
csr, csrPEM, _, err := makeCSRAndKey()
csr, csrPEM, keyPEM, err := makeCSRAndKey()
if err != nil {
log.Fatal(err)
}
if *debug {
fmt.Printf("%s\n%s\n", csrPEM, keyPEM)
}
// Step 2: submit an order to digicert
var order digigo.Order
order.Certificate.CommonName = csr.Subject.CommonName
order.Certificate.DNSNames = csr.DNSNames
order.Certificate.Csr = csrPEM
order.Certificate.OrganizationUnits = csr.Subject.OrganizationalUnit
order.Certificate.ServerPlatform.ID = 45 // nginx, aka. standard PEM
@ -57,10 +68,11 @@ func main() {
order.Certificate.SignatureHash = "sha256"
}
// FIXME: actually call ListOrganizations
order.Organization.ID = 110462 // mozilla org ID
orderID, err := cli.SubmitOrder(order, "ssl_plus")
order.Organization.ID = 147486 // mozilla org ID
orderID, err := cli.SubmitOrder(order, "ssl")
if err != nil {
log.Fatal(err)
}
log.Println(orderID)
log.Println("placed order with ID", orderID)
}

Просмотреть файл

@ -18,7 +18,7 @@ import (
"github.com/pkg/errors"
)
func makeCSRAndKey() (csr x509.CertificateRequest, csrPEM, privKeyPEM string, err error) {
func makeCSRAndKey() (csr *x509.CertificateRequest, csrPEM, privKeyPEM string, err error) {
var priv interface{}
switch *ecdsaCurve {
case "":
@ -57,6 +57,11 @@ func makeCSRAndKey() (csr x509.CertificateRequest, csrPEM, privKeyPEM string, er
err = errors.Wrap(err, "failed to generate CSR")
return
}
csr, err = x509.ParseCertificateRequest(csrB)
if err != nil {
err = errors.Wrap(err, "failed to parse CSR")
return
}
// convert the CSR bytes to PEM
var csrBuf bytes.Buffer
pem.Encode(&csrBuf, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrB})

30
errors.go Normal file
Просмотреть файл

@ -0,0 +1,30 @@
package digigo // import "go.mozilla.org/digigo"
import "fmt"
// Errors is a list of error returned by the Digicert API
// https://www.digicert.com/services/v2/documentation/errors
type Errors struct {
Errors []Error `json:"errors"`
}
// Error returned by Digicert has a code and a message
type Error struct {
Code string `json:"code"`
Message string `json:"message"`
}
// Print several errors into a single string
func (errors Errors) String() string {
if len(errors.Errors) == 1 {
return fmt.Sprintf("%s %s",
errors.Errors[0].Code, errors.Errors[0].Message)
}
var str string
for i, e := range errors.Errors {
if str != "" {
str += " "
}
str += fmt.Sprintf("%d) %s %s", i, e.Code, e.Message)
}
return str
}

45
main.go
Просмотреть файл

@ -4,9 +4,13 @@ package digigo // import "go.mozilla.org/digigo"
import (
"crypto/tls"
"fmt"
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"github.com/fatih/color"
"github.com/pkg/errors"
)
@ -63,12 +67,16 @@ func (cli *Client) DisableDebug() {
// Do is a thin wrapper around http.Client.Do() that inserts an authentication header
// to the outgoing request and checks response codes
func (cli Client) Do(r *http.Request) (*http.Response, error) {
r.Header.Set("User-Agent", "Digicert Go Client "+Version)
r.Header.Set("User-Agent", "go.mozilla.org/digigo "+Version)
r.Header.Set("X-DC-DEVKEY", cli.token)
r.Header.Set("Accept", "application/json")
r.Header.Set("Content-Type", "application/json")
if cli.debug {
fmt.Printf("debug: %s %s %s\ndebug: User-Agent: %s\ndebug: X-DC-DEVKEY: %s\n",
r.Method, r.URL.String(), r.Proto, r.UserAgent(), r.Header.Get("X-DC-DEVKEY"))
dump, err := httputil.DumpRequest(r, true)
if err != nil {
log.Fatal("failed to dump request in debug mode: ", err)
}
color.Green("--- debug: client request ---\n%s\n-----------------------------\n", dump)
}
// execute the request
resp, err := cli.requester.Do(r)
@ -76,10 +84,33 @@ func (cli Client) Do(r *http.Request) (*http.Response, error) {
return nil, errors.New("received empty response from digicert api")
}
if err != nil {
return nil, errors.Wrapf(err, "failed to request the digicert api: %d %s", resp.StatusCode, resp.Status)
return nil, errors.Wrapf(err, "failed to request the digicert api: %s", resp.Status)
}
if resp.StatusCode > 200 {
return nil, errors.Errorf("failed to request the digicert api: %d %s", resp.StatusCode, resp.Status)
if cli.debug {
dump, err := httputil.DumpResponse(resp, true)
if err != nil {
log.Fatal("failed to dump response in debug mode: ", err)
}
color.Red("--- debug: digicert response ---\n%s\n--------------------------------\n", dump)
}
if resp.StatusCode >= 300 {
if resp.Body != nil {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Errorf("failed to request the digicert api: %s. couldn't parse returned error %q: %s",
resp.Status, body, err)
}
var errs Errors
err = json.Unmarshal(body, &errs)
if err != nil {
return nil, errors.Errorf("failed to request the digicert api: %s. couldn't parse returned error %q: %s",
resp.Status, body, errs)
}
return nil, errors.Errorf("failed to request the digicert api: %s, %s", resp.Status, errs)
}
return nil, errors.Errorf("failed to request the digicert api: %s. no error was returned.", resp.Status)
}
return resp, nil
}

Просмотреть файл

@ -13,23 +13,24 @@ import (
type Order struct {
Certificate struct {
CommonName string `json:"common_name"`
DNSNames []string `json:"dns_names"`
Csr string `json:"csr"`
OrganizationUnits []string `json:"organization_units"`
OrganizationUnits []string `json:"organization_units,omitempty"`
ServerPlatform struct {
ID int `json:"id"`
} `json:"server_platform"`
} `json:"server_platform,omitempty"`
SignatureHash string `json:"signature_hash"`
ProfileOption string `json:"profile_option"`
ProfileOption string `json:"profile_option,omitempty"`
} `json:"certificate"`
Organization struct {
ID int `json:"id"`
} `json:"organization"`
ValidityYears int `json:"validity_years"`
CustomExpirationDate string `json:"custom_expiration_date"`
Comments string `json:"comments"`
DisableRenewalNotifications bool `json:"disable_renewal_notifications"`
RenewalOfOrderID int `json:"renewal_of_order_id"`
PaymentMethod string `json:"payment_method"`
CustomExpirationDate string `json:"custom_expiration_date,omitempty"`
Comments string `json:"comments,omitempty"`
DisableRenewalNotifications bool `json:"disable_renewal_notifications,omitempty"`
RenewalOfOrderID int `json:"renewal_of_order_id,omitempty"`
PaymentMethod string `json:"payment_method,omitempty"`
}
type orderResponse struct {
@ -61,7 +62,7 @@ func (cli Client) SubmitOrder(order Order, productNameID string) (int, error) {
return -1, errors.Wrap(err, "failed to submit request to digicert api")
}
if resp.StatusCode != http.StatusCreated {
return -1, errors.Errorf("failed to create order: http %d %s", resp.StatusCode, resp.Status)
return -1, errors.Errorf("failed to create order: %s", resp.Status)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {