1
0
mirror of https://github.com/go-acme/lego.git synced 2024-12-22 07:12:22 +02:00

chore: update to go1.20 (#1993)

This commit is contained in:
Ludovic Fernandez 2023-08-19 18:05:33 +02:00 committed by GitHub
parent c365d7efc8
commit b37d60c033
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 144 additions and 92 deletions

View File

@ -11,7 +11,7 @@ jobs:
name: Build and deploy documentation
runs-on: ubuntu-latest
env:
GO_VERSION: '1.20'
GO_VERSION: stable
HUGO_VERSION: '0.117.0'
CGO_ENABLED: 0

View File

@ -16,37 +16,19 @@ jobs:
strategy:
matrix:
go-version: [ '1.19', '1.20', 1.x ]
go-version: [ stable, oldstable ]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
# https://github.com/marketplace/actions/checkout
- name: Checkout code
uses: actions/checkout@v3
# https://github.com/marketplace/actions/cache
- name: Cache Go modules
uses: actions/cache@v3
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v4
with:
# In order:
# * Module download cache
# * Build cache (Linux)
# * Build cache (Mac)
# * Build cache (Windows)
path: |
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
%LocalAppData%\go-build
key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-${{ matrix.go-version }}-go-
go-version: ${{ matrix.go-version }}
- name: Test
run: go test -v -cover ./...

View File

@ -12,8 +12,8 @@ jobs:
name: Main Process
runs-on: ubuntu-latest
env:
GO_VERSION: '1.20'
GOLANGCI_LINT_VERSION: v1.53.1
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v1.54.1
HUGO_VERSION: '0.117.0'
CGO_ENABLED: 0
LEGO_E2E_TESTS: CI
@ -21,26 +21,17 @@ jobs:
steps:
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
# https://github.com/marketplace/actions/checkout
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0
# https://github.com/marketplace/actions/cache
- name: Cache Go modules
uses: actions/cache@v3
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
go-version: ${{ env.GO_VERSION }}
- name: Check and get dependencies
run: |

View File

@ -11,7 +11,7 @@ jobs:
name: Release version
runs-on: ubuntu-latest
env:
GO_VERSION: '1.20'
GO_VERSION: stable
CGO_ENABLED: 0
steps:

View File

@ -35,13 +35,14 @@ func (c *Certifier) getAuthorizations(order acme.ExtendedOrder) ([]acme.Authoriz
}
var responses []acme.Authorization
failures := make(obtainError)
failures := newObtainError()
for i := 0; i < len(order.Authorizations); i++ {
select {
case res := <-resc:
responses = append(responses, res)
case err := <-errc:
failures[err.Domain] = err.Error
failures.Add(err.Domain, err.Error)
}
}
@ -52,12 +53,7 @@ func (c *Certifier) getAuthorizations(order acme.ExtendedOrder) ([]acme.Authoriz
close(resc)
close(errc)
// be careful to not return an empty failures map;
// even if empty, they become non-nil error values
if len(failures) > 0 {
return responses, failures
}
return responses, nil
return responses, failures.Join()
}
func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder, force bool) {

View File

@ -149,11 +149,11 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
failures := make(obtainError)
failures := newObtainError()
cert, err := c.getForOrder(domains, order, request.Bundle, request.PrivateKey, request.MustStaple, request.PreferredChain)
if err != nil {
for _, auth := range authz {
failures[challenge.GetTargetedDomain(auth)] = err
failures.Add(challenge.GetTargetedDomain(auth), err)
}
}
@ -161,12 +161,7 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
c.deactivateAuthorizations(order, true)
}
// Do not return an empty failures map, because
// it would still be a non-nil error value
if len(failures) > 0 {
return cert, failures
}
return cert, nil
return cert, failures.Join()
}
// ObtainForCSR tries to obtain a certificate matching the CSR passed into it.
@ -219,11 +214,11 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
failures := make(obtainError)
failures := newObtainError()
cert, err := c.getForCSR(domains, order, request.Bundle, request.CSR.Raw, nil, request.PreferredChain)
if err != nil {
for _, auth := range authz {
failures[challenge.GetTargetedDomain(auth)] = err
failures.Add(challenge.GetTargetedDomain(auth), err)
}
}
@ -236,12 +231,7 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
cert.CSR = certcrypto.PEMEncode(request.CSR)
}
// Do not return an empty failures map,
// because it would still be a non-nil error value
if len(failures) > 0 {
return cert, failures
}
return cert, nil
return cert, failures.Join()
}
func (c *Certifier) getForOrder(domains []string, order acme.ExtendedOrder, bundle bool, privateKey crypto.PrivateKey, mustStaple bool, preferredChain string) (*Resource, error) {

View File

@ -1,27 +1,37 @@
package certificate
import (
"bytes"
"errors"
"fmt"
"sort"
)
// obtainError is returned when there are specific errors available per domain.
type obtainError map[string]error
type obtainError struct {
data map[string]error
}
func (e obtainError) Error() string {
buffer := bytes.NewBufferString("error: one or more domains had a problem:\n")
func newObtainError() *obtainError {
return &obtainError{data: make(map[string]error)}
}
var domains []string
for domain := range e {
domains = append(domains, domain)
func (e *obtainError) Add(domain string, err error) {
e.data[domain] = err
}
func (e *obtainError) Join() error {
if e == nil {
return nil
}
sort.Strings(domains)
for _, domain := range domains {
_, _ = fmt.Fprintf(buffer, "[%s] %s\n", domain, e[domain])
if len(e.data) == 0 {
return nil
}
return buffer.String()
var err error
for d, e := range e.data {
err = errors.Join(err, fmt.Errorf("%s: %w", d, e))
}
return fmt.Errorf("error: one or more domains had a problem:\n%w", err)
}
type domainError struct {

View File

@ -0,0 +1,70 @@
package certificate
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type TomatoError struct{}
func (t TomatoError) Error() string {
return "tomato"
}
type CarrotError struct{}
func (t CarrotError) Error() string {
return "carrot"
}
func Test_obtainError_Join(t *testing.T) {
failures := newObtainError()
failures.Add("example.com", &TomatoError{})
err := failures.Join()
to := &TomatoError{}
assert.ErrorAs(t, err, &to)
}
func Test_obtainError_Join_multiple_domains(t *testing.T) {
failures := newObtainError()
failures.Add("example.com", &TomatoError{})
failures.Add("example.org", &CarrotError{})
err := failures.Join()
to := &TomatoError{}
assert.ErrorAs(t, err, &to)
ca := &CarrotError{}
assert.ErrorAs(t, err, &ca)
}
func Test_obtainError_Join_no_error(t *testing.T) {
failures := newObtainError()
assert.NoError(t, failures.Join())
}
func Test_obtainError_Join_same_domain(t *testing.T) {
failures := newObtainError()
failures.Add("example.com", &TomatoError{})
failures.Add("example.com", &CarrotError{})
err := failures.Join()
to := &TomatoError{}
if errors.As(err, &to) {
require.Fail(t, "TomatoError should be overridden by CarrotError")
}
ca := &CarrotError{}
assert.ErrorAs(t, err, &ca)
}

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/go-acme/lego/v4
go 1.19
go 1.20
require (
cloud.google.com/go/compute/metadata v0.2.3

View File

@ -54,7 +54,7 @@ type DNSRequest struct {
// ---
type GetDNSSettingsAPIResponse struct {
Response GetDNSSettingsResponse `json:"Response" mapstructure:"Response"`
Response GetDNSSettingsResponse `json:"Response" mapstructure:"Response"`
}
type GetDNSSettingsResponse struct {

View File

@ -11,26 +11,26 @@ import (
"time"
"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
"golang.org/x/oauth2"
)
const defaultBaseURL = "https://ipv64.net"
const authorizationHeader = "Authorization"
type Client struct {
apiKey string
baseURL *url.URL
HTTPClient *http.Client
}
func NewClient(apiKey string) *Client {
func NewClient(hc *http.Client) *Client {
baseURL, _ := url.Parse(defaultBaseURL)
if hc == nil {
hc = &http.Client{Timeout: 15 * time.Second}
}
return &Client{
apiKey: apiKey,
baseURL: baseURL,
HTTPClient: &http.Client{Timeout: 15 * time.Second},
HTTPClient: hc,
}
}
@ -91,8 +91,6 @@ func (c Client) DeleteRecord(ctx context.Context, domain, prefix, recordType, co
}
func (c Client) do(req *http.Request, result any) error {
req.Header.Set(authorizationHeader, fmt.Sprintf("Bearer %s", c.apiKey))
if req.Method != http.MethodGet {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
@ -140,3 +138,16 @@ func parseError(req *http.Request, resp *http.Response) error {
return errAPI
}
func OAuthStaticAccessToken(client *http.Client, accessToken string) *http.Client {
if client == nil {
client = &http.Client{Timeout: 15 * time.Second}
}
client.Transport = &oauth2.Transport{
Source: oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken}),
Base: client.Transport,
}
return client
}

View File

@ -15,12 +15,14 @@ import (
"github.com/stretchr/testify/require"
)
const testAPIKey = "secret"
func setupTest(t *testing.T, handler http.HandlerFunc) *Client {
t.Helper()
server := httptest.NewServer(handler)
client := NewClient("secret")
client := NewClient(OAuthStaticAccessToken(server.Client(), testAPIKey))
client.HTTPClient = server.Client()
client.baseURL, _ = url.Parse(server.URL)
@ -34,8 +36,8 @@ func testHandler(method, filename string, statusCode int) http.HandlerFunc {
return
}
auth := req.Header.Get(authorizationHeader)
if auth != "Bearer secret" {
auth := req.Header.Get("Authorization")
if auth != "Bearer "+testAPIKey {
http.Error(rw, fmt.Sprintf("invalid API key: %s", auth), http.StatusUnauthorized)
return
}

View File

@ -78,7 +78,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, errors.New("ipv64: credentials missing")
}
client := internal.NewClient(config.APIKey)
client := internal.NewClient(internal.OAuthStaticAccessToken(config.HTTPClient, config.APIKey))
if config.HTTPClient != nil {
client.HTTPClient = config.HTTPClient