| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package acme
- import (
- "crypto"
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "reflect"
- )
- // NewAccount registers a new account with the acme service
- // Note this function is essentially deprecated and only present for backwards compatibility.
- // New programs should implement NewAccountOptions instead.
- func (c Client) NewAccount(privateKey crypto.Signer, onlyReturnExisting, termsOfServiceAgreed bool, contact ...string) (Account, error) {
- var opts []NewAccountOptionFunc
- if onlyReturnExisting {
- opts = append(opts, NewAcctOptOnlyReturnExisting())
- }
- if termsOfServiceAgreed {
- opts = append(opts, NewAcctOptAgreeTOS())
- }
- if len(contact) > 0 {
- opts = append(opts, NewAcctOptWithContacts(contact...))
- }
- return c.NewAccountOptions(privateKey, opts...)
- }
- // NewAccountOptions registers an account with an acme server with the provided options.
- func (c Client) NewAccountOptions(privateKey crypto.Signer, options ...NewAccountOptionFunc) (Account, error) {
- newAccountReq := NewAccountRequest{}
- account := Account{}
- for _, opt := range options {
- if err := opt(privateKey, &account, &newAccountReq, c); err != nil {
- return account, err
- }
- }
- resp, err := c.post(c.dir.NewAccount, "", privateKey, newAccountReq, &account, http.StatusOK, http.StatusCreated)
- if err != nil {
- return account, err
- }
- account.URL = resp.Header.Get("Location")
- account.PrivateKey = privateKey
- if account.Thumbprint == "" {
- account.Thumbprint, err = JWKThumbprint(account.PrivateKey.Public())
- if err != nil {
- return account, fmt.Errorf("acme: error computing account thumbprint: %v", err)
- }
- }
- return account, nil
- }
- // UpdateAccount updates an existing account with the acme service.
- func (c Client) UpdateAccount(account Account, contact ...string) (Account, error) {
- var updateAccountReq interface{}
- if !reflect.DeepEqual(account.Contact, contact) {
- // Only provide a non-nil updateAccountReq when there is an update to be made.
- updateAccountReq = struct {
- Contact []string `json:"contact,omitempty"`
- }{
- Contact: contact,
- }
- } else {
- // Otherwise use "" to trigger a POST-as-GET to fetch up-to-date account
- // information from the acme service.
- updateAccountReq = ""
- }
- _, err := c.post(account.URL, account.URL, account.PrivateKey, updateAccountReq, &account, http.StatusOK)
- if err != nil {
- return account, err
- }
- if account.Thumbprint == "" {
- account.Thumbprint, err = JWKThumbprint(account.PrivateKey.Public())
- if err != nil {
- return account, fmt.Errorf("acme: error computing account thumbprint: %v", err)
- }
- }
- return account, nil
- }
- // AccountKeyChange rolls over an account to a new key.
- func (c Client) AccountKeyChange(account Account, newPrivateKey crypto.Signer) (Account, error) {
- oldJwkKeyPub, err := jwkEncode(account.PrivateKey.Public())
- if err != nil {
- return account, fmt.Errorf("acme: error encoding new private key: %v", err)
- }
- keyChangeReq := struct {
- Account string `json:"account"`
- OldKey json.RawMessage `json:"oldKey"`
- }{
- Account: account.URL,
- OldKey: []byte(oldJwkKeyPub),
- }
- innerJws, err := jwsEncodeJSON(keyChangeReq, newPrivateKey, "", "", c.dir.KeyChange)
- if err != nil {
- return account, fmt.Errorf("acme: error encoding inner jws: %v", err)
- }
- if _, err := c.post(c.dir.KeyChange, account.URL, account.PrivateKey, json.RawMessage(innerJws), nil, http.StatusOK); err != nil {
- return account, err
- }
- account.PrivateKey = newPrivateKey
- return account, nil
- }
- // DeactivateAccount deactivates a given account.
- func (c Client) DeactivateAccount(account Account) (Account, error) {
- deactivateReq := struct {
- Status string `json:"status"`
- }{
- Status: "deactivated",
- }
- _, err := c.post(account.URL, account.URL, account.PrivateKey, deactivateReq, &account, http.StatusOK)
- return account, err
- }
- // FetchOrderList fetches a list of orders from the account url provided in the account Orders field
- func (c Client) FetchOrderList(account Account) (OrderList, error) {
- orderList := OrderList{}
- if account.Orders == "" {
- return orderList, errors.New("no order list for account")
- }
- _, err := c.post(account.Orders, account.URL, account.PrivateKey, "", &orderList, http.StatusOK)
- return orderList, err
- }
|