generateZeroSSLEABCredentials generates ZeroSSL EAB credentials for the primary contact email on the issuer. It should only be usedif the CA endpoint is ZeroSSL. An email address is required.
(ctx context.Context, acct acme.Account)
| 362 | // generateZeroSSLEABCredentials generates ZeroSSL EAB credentials for the primary contact email |
| 363 | // on the issuer. It should only be usedif the CA endpoint is ZeroSSL. An email address is required. |
| 364 | func (iss *ACMEIssuer) generateZeroSSLEABCredentials(ctx context.Context, acct acme.Account) (*acme.EAB, acme.Account, error) { |
| 365 | if strings.TrimSpace(iss.Email) == "" { |
| 366 | return nil, acme.Account{}, fmt.Errorf("your email address is required to use ZeroSSL's ACME endpoint") |
| 367 | } |
| 368 | |
| 369 | if len(acct.Contact) == 0 { |
| 370 | // we borrow the email from config or the default email, so ensure it's saved with the account |
| 371 | acct.Contact = []string{"mailto:" + iss.Email} |
| 372 | } |
| 373 | |
| 374 | endpoint := zerossl.BaseURL + "/acme/eab-credentials-email" |
| 375 | form := url.Values{"email": []string{iss.Email}} |
| 376 | body := strings.NewReader(form.Encode()) |
| 377 | |
| 378 | req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body) |
| 379 | if err != nil { |
| 380 | return nil, acct, fmt.Errorf("forming request: %v", err) |
| 381 | } |
| 382 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| 383 | req.Header.Set("User-Agent", certmagic.UserAgent) |
| 384 | |
| 385 | resp, err := http.DefaultClient.Do(req) //nolint:gosec // no SSRF since URL is from trusted config |
| 386 | if err != nil { |
| 387 | return nil, acct, fmt.Errorf("performing EAB credentials request: %v", err) |
| 388 | } |
| 389 | defer resp.Body.Close() |
| 390 | |
| 391 | var result struct { |
| 392 | Success bool `json:"success"` |
| 393 | Error struct { |
| 394 | Code int `json:"code"` |
| 395 | Type string `json:"type"` |
| 396 | } `json:"error"` |
| 397 | EABKID string `json:"eab_kid"` |
| 398 | EABHMACKey string `json:"eab_hmac_key"` |
| 399 | } |
| 400 | err = json.NewDecoder(resp.Body).Decode(&result) |
| 401 | if err != nil { |
| 402 | return nil, acct, fmt.Errorf("decoding API response: %v", err) |
| 403 | } |
| 404 | if result.Error.Code != 0 { |
| 405 | // do this check first because ZeroSSL's API returns 200 on errors |
| 406 | return nil, acct, fmt.Errorf("failed getting EAB credentials: HTTP %d: %s (code %d)", |
| 407 | resp.StatusCode, result.Error.Type, result.Error.Code) |
| 408 | } |
| 409 | if resp.StatusCode != http.StatusOK { |
| 410 | return nil, acct, fmt.Errorf("failed getting EAB credentials: HTTP %d", resp.StatusCode) |
| 411 | } |
| 412 | |
| 413 | if c := iss.logger.Check(zapcore.InfoLevel, "generated EAB credentials"); c != nil { |
| 414 | c.Write(zap.String("key_id", result.EABKID)) |
| 415 | } |
| 416 | |
| 417 | return &acme.EAB{ |
| 418 | KeyID: result.EABKID, |
| 419 | MACKey: result.EABHMACKey, |
| 420 | }, acct, nil |
| 421 | } |