wip: make order submission work
This commit is contained in:
Родитель
8d08731b0f
Коммит
6190c2cb00
|
@ -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})
|
||||
|
|
|
@ -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
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
|
||||
}
|
||||
|
|
19
order.go
19
order.go
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче