Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe13e8dff6 | |||
10d070dd10 | |||
af826ff457 | |||
90bfc25975 | |||
dadb907740 | |||
bfb5ee44ce | |||
87eac3e11b | |||
60cc3f4073 | |||
d952775922 | |||
2c822aeade | |||
aea5c7619f | |||
dc90ed4488 | |||
b20b1719bd | |||
99a03bac5d | |||
4e68821594 | |||
d5159b447a | |||
4e23987412 | |||
62af54fbb8 | |||
5615ae297a | |||
6a708d748b |
159
.drone.yml
159
.drone.yml
@ -1,89 +1,70 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: cleanup-before
|
||||
name: build-linux
|
||||
|
||||
environment:
|
||||
GOOS: linux
|
||||
GOOPTIONS: -mod=vendor
|
||||
SRCFILES: cmd/pki/*.go
|
||||
PROJECTNAME: pki
|
||||
|
||||
steps:
|
||||
- name: clean
|
||||
image: alpine
|
||||
commands:
|
||||
- rm -rf /build/*
|
||||
volumes:
|
||||
- name: build
|
||||
path: /build
|
||||
when:
|
||||
event: tag
|
||||
|
||||
volumes:
|
||||
- name: build
|
||||
host:
|
||||
path: /tmp/pki/build
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default-linux-amd64
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
- name: build-linux-amd64
|
||||
image: golang
|
||||
commands:
|
||||
- ./ci-build.sh build
|
||||
- go build -o $PROJECTNAME $GOOPTIONS $SRCFILES
|
||||
environment:
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
volumes:
|
||||
- name: build
|
||||
path: /build
|
||||
|
||||
volumes:
|
||||
- name: build
|
||||
host:
|
||||
path: /tmp/pki/build
|
||||
|
||||
depends_on:
|
||||
- cleanup-before
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default-linux-arm64
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
- name: build-linux-arm64
|
||||
image: golang
|
||||
commands:
|
||||
- ./ci-build.sh build
|
||||
- go build -o $PROJECTNAME $GOOPTIONS $SRCFILES
|
||||
environment:
|
||||
GOOS: linux
|
||||
GOARCH: arm64
|
||||
volumes:
|
||||
- name: build
|
||||
path: /build
|
||||
|
||||
volumes:
|
||||
- name: build
|
||||
host:
|
||||
path: /tmp/pki/build
|
||||
|
||||
depends_on:
|
||||
- cleanup-before
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: gitea-release
|
||||
name: gitea-release-linux
|
||||
|
||||
environment:
|
||||
GOOS: linux
|
||||
GOOPTIONS: -mod=vendor
|
||||
SRCFILES: cmd/pki/*.go
|
||||
PROJECTNAME: pki
|
||||
|
||||
steps:
|
||||
- name: move
|
||||
image: alpine
|
||||
- name: build-linux-amd64
|
||||
image: golang
|
||||
commands:
|
||||
- mv build/* ./
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/src/build
|
||||
- go build -o $PROJECTNAME $GOOPTIONS $SRCFILES
|
||||
- tar -czvf $PROJECTNAME-$DRONE_TAG-$GOOS-$GOARCH.tar.gz $PROJECTNAME
|
||||
- echo $PROJECTNAME $DRONE_TAG > VERSION
|
||||
environment:
|
||||
GOARCH: amd64
|
||||
when:
|
||||
event: tag
|
||||
event:
|
||||
- tag
|
||||
- name: build-linux-arm64
|
||||
image: golang
|
||||
commands:
|
||||
- go build -o $PROJECTNAME $GOOPTIONS $SRCFILES
|
||||
- tar -czvf $PROJECTNAME-$DRONE_TAG-$GOOS-$GOARCH.tar.gz $PROJECTNAME
|
||||
- echo $PROJECTNAME $DRONE_TAG > VERSION
|
||||
environment:
|
||||
GOARCH: arm64
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
- name: release
|
||||
image: plugins/gitea-release
|
||||
settings:
|
||||
@ -95,50 +76,6 @@ steps:
|
||||
- sha256
|
||||
- sha512
|
||||
title: VERSION
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/src/build
|
||||
when:
|
||||
event: tag
|
||||
- name: ls
|
||||
image: alpine
|
||||
commands:
|
||||
- find .
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/src/build
|
||||
when:
|
||||
event: tag
|
||||
|
||||
volumes:
|
||||
- name: build
|
||||
host:
|
||||
path: /tmp/pki/build
|
||||
|
||||
depends_on:
|
||||
- default-linux-amd64
|
||||
- default-linux-arm64
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: cleanup-after
|
||||
|
||||
steps:
|
||||
- name: clean
|
||||
image: alpine
|
||||
commands:
|
||||
- rm -rf /build/*
|
||||
volumes:
|
||||
- name: build
|
||||
path: /build
|
||||
when:
|
||||
event: tag
|
||||
|
||||
volumes:
|
||||
- name: build
|
||||
host:
|
||||
path: /tmp/pki/build
|
||||
|
||||
depends_on:
|
||||
- gitea-release
|
||||
event:
|
||||
- tag
|
||||
|
18
Makefile
18
Makefile
@ -1,18 +0,0 @@
|
||||
# pki Makefile
|
||||
|
||||
GOCMD=go
|
||||
GOBUILDCMD=${GOCMD} build
|
||||
GOOPTIONS=-mod=vendor -ldflags="-s -w"
|
||||
|
||||
RMCMD=rm
|
||||
BINNAME=pki
|
||||
|
||||
SRCFILES=cmd/pki/*.go
|
||||
|
||||
all: build
|
||||
|
||||
build:
|
||||
${GOBUILDCMD} ${GOOPTIONS} ${SRCFILES}
|
||||
|
||||
clean:
|
||||
${RMCMD} -f ${BINNAME}
|
@ -10,7 +10,7 @@ PKI is a centralized Letsencrypt database server and renewer for certificate man
|
||||
### Build
|
||||
|
||||
```bash
|
||||
make
|
||||
go build cmd/pki/pki.go
|
||||
```
|
||||
|
||||
### Sample config in pki.ini
|
||||
@ -40,7 +40,7 @@ ovhck=
|
||||
## License
|
||||
|
||||
```text
|
||||
Copyright (c) 2020, 2021 PaulBSD
|
||||
Copyright (c) 2020, 2021, 2022 PaulBSD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
62
ci-build.sh
62
ci-build.sh
@ -1,62 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PROJECTNAME=pki
|
||||
RELEASENAME=${PROJECTNAME}
|
||||
VERSION="0"
|
||||
|
||||
GOOPTIONS="-mod=vendor"
|
||||
SRCFILES=cmd/${PROJECTNAME}/*.go
|
||||
|
||||
build() {
|
||||
echo "Begin of build"
|
||||
if [[ ! -z $DRONE_TAG ]]
|
||||
then
|
||||
echo "Drone tag set, let's do a release"
|
||||
VERSION=$DRONE_TAG
|
||||
echo "${PROJECTNAME} ${VERSION}" > /build/VERSION
|
||||
elif [[ ! -z $DRONE_TAG ]]
|
||||
then
|
||||
echo "Drone not set, let's only do a build"
|
||||
VERSION=$DRONE_COMMIT
|
||||
fi
|
||||
|
||||
if [[ ! -z $VERSION && ! -z $GOOS && ! -z $GOARCH ]]
|
||||
then
|
||||
echo "Let's set a release name"
|
||||
RELEASENAME=${PROJECTNAME}-${VERSION}-${GOOS}-${GOARCH}
|
||||
fi
|
||||
|
||||
echo "Building project"
|
||||
go build -o ${PROJECTNAME} ${GOOPTIONS} ${SRCFILES}
|
||||
|
||||
if [[ ! -z $DRONE_TAG ]]
|
||||
then
|
||||
echo "Let's make archives"
|
||||
mkdir -p /build
|
||||
tar -czvf /build/${RELEASENAME}.tar.gz ${PROJECTNAME}
|
||||
fi
|
||||
|
||||
echo "Removing binary file"
|
||||
rm ${PROJECTNAME}
|
||||
|
||||
echo "End of build"
|
||||
}
|
||||
|
||||
clean() {
|
||||
rm -rf $RELEASEDIR
|
||||
}
|
||||
|
||||
case $1 in
|
||||
"build")
|
||||
build
|
||||
;;
|
||||
"clean")
|
||||
clean
|
||||
;;
|
||||
*)
|
||||
echo "No options choosen"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
53
go.mod
53
go.mod
@ -1,25 +1,42 @@
|
||||
module git.paulbsd.com/paulbsd/pki
|
||||
|
||||
go 1.16
|
||||
go 1.23
|
||||
|
||||
require (
|
||||
github.com/go-acme/lego/v4 v4.3.1
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20210406100015-1e088ea4ee04 // indirect
|
||||
github.com/labstack/echo/v4 v4.2.1
|
||||
github.com/lib/pq v1.10.0
|
||||
github.com/mattn/go-sqlite3 v1.14.6 // indirect
|
||||
github.com/miekg/dns v1.1.41 // indirect
|
||||
github.com/go-acme/lego/v4 v4.17.4
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/labstack/echo/v4 v4.12.0
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/onsi/ginkgo v1.16.0 // indirect
|
||||
github.com/onsi/gomega v1.11.0 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
xorm.io/builder v0.3.9 // indirect
|
||||
xorm.io/xorm v1.0.7
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
xorm.io/builder v0.3.13 // indirect
|
||||
xorm.io/xorm v1.3.9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/ovh/go-ovh v1.6.0 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/oauth2 v0.22.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
)
|
||||
|
778
go.sum
778
go.sum
@ -1,148 +1,34 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.0/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.976/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.37.27/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc=
|
||||
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deepmap/oapi-codegen v1.3.11/go.mod h1:suMvK7+rKlx3+tpa8ByptmvoXbAV70wERKTOGH3hLp0=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exoscale/egoscale v0.46.0/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-acme/lego/v4 v4.3.1 h1:rzmg0Gpy25B/exXjl+KgpG5Xt6wN5rFTLjRf/Uf3pfg=
|
||||
github.com/go-acme/lego/v4 v4.3.1/go.mod h1:tySA24ifl6bI7kZ0+ocGtTIv4H1yhYVFAgyMHF2DSRg=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-acme/lego/v4 v4.16.1 h1:JxZ93s4KG0jL27rZ30UsIgxap6VGzKuREsSkkyzeoCQ=
|
||||
github.com/go-acme/lego/v4 v4.16.1/go.mod h1:AVvwdPned/IWpD/ihHhMsKnveF7HHYAz/CmtXi7OZoE=
|
||||
github.com/go-acme/lego/v4 v4.17.4 h1:h0nePd3ObP6o7kAkndtpTzCw8shOZuWckNYeUQwo36Q=
|
||||
github.com/go-acme/lego/v4 v4.17.4/go.mod h1:dU94SvPNqimEeb7EVilGGSnS0nU1O5Exir0pQ4QFL4U=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
@ -151,166 +37,50 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||
github.com/gophercloud/gophercloud v0.16.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4=
|
||||
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20210406100015-1e088ea4ee04 h1:Enykqupm0u6qiUZAc+SiFkMJVqt4o8knNcKJu8NdlJ0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20210406100015-1e088ea4ee04/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
|
||||
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/echo/v4 v4.2.1 h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw=
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
||||
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linode/linodego v0.25.3/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE=
|
||||
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
|
||||
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
|
||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/nrdcg/auroradns v1.0.1/go.mod h1:y4pc0i9QXYlFCWrhWrUSIETnZgrf4KuwjDIWmmXo3JI=
|
||||
github.com/nrdcg/desec v0.5.0/go.mod h1:2ejvMazkav1VdDbv2HeQO7w+Ta1CGHqzQr27ZBYTuEQ=
|
||||
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||
github.com/nrdcg/goinwx v0.8.1/go.mod h1:tILVc10gieBp/5PMvbcYeXM6pVQ+c9jxDZnpaR1UW7c=
|
||||
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
@ -321,418 +91,138 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
|
||||
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||
github.com/ovh/go-ovh v1.1.0 h1:bHXZmw8nTgZin4Nv7JuaLs0KG5x54EQR7migYTd1zrk=
|
||||
github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
|
||||
github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI=
|
||||
github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||
github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI=
|
||||
github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/transip/gotransip/v6 v6.6.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vultr/govultr/v2 v2.4.0/go.mod h1:U+dZLAmyGD62IGykgC9JYU/zQIOkIhf93nw6dJL/47M=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
|
||||
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
|
||||
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ns1/ns1-go.v2 v2.4.4/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYhsPk=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.9 h1:Sd65/LdWyO7LR8+Cbd+e7mm3sK/7U9k0jS3999IDHMc=
|
||||
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.0.7 h1:26yBTDVI+CfQpVz2Y88fISh+aiJXIPP4eNoTJlwzsC4=
|
||||
xorm.io/xorm v1.0.7/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0=
|
||||
modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.20.4 h1:J8+m2trkN+KKoE7jglyHYYYiaq5xmz2HoHJIiBlRzbE=
|
||||
modernc.org/sqlite v1.20.4/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||
|
@ -2,10 +2,13 @@ package cert
|
||||
|
||||
import "time"
|
||||
|
||||
func (e *Entry) Z() {
|
||||
}
|
||||
|
||||
// Entry is the main struct for stored certificates
|
||||
type Entry struct {
|
||||
ID int `xorm:"pk autoincr"`
|
||||
Domains string `xorm:"notnull"`
|
||||
Domain string `xorm:"notnull"`
|
||||
Certificate string `xorm:"text notnull"`
|
||||
PrivateKey string `xorm:"text notnull"`
|
||||
AuthURL string `xorm:"notnull"`
|
||||
|
@ -60,10 +60,13 @@ func (cfg *Config) GetConfig() error {
|
||||
options["ovhas"] = pkisection.Key("ovhas").MustString("")
|
||||
options["ovhck"] = pkisection.Key("ovhck").MustString("")
|
||||
|
||||
options["pdnsapiurl"] = pkisection.Key("pdnsapiurl").MustString("")
|
||||
options["pdnsapikey"] = pkisection.Key("pdnsapikey").MustString("")
|
||||
|
||||
cfg.ACME.ProviderOptions = options
|
||||
for k, v := range options {
|
||||
if v == "" {
|
||||
utils.Advice(fmt.Sprintf("OVH provider parameter %s not set", k))
|
||||
for key, value := range options {
|
||||
if value == "" {
|
||||
utils.Advice(fmt.Sprintf("Provider parameter %s not set", key))
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +75,8 @@ func (cfg *Config) GetConfig() error {
|
||||
cfg.ACME.AuthURL = lego.LEDirectoryProduction
|
||||
case "staging":
|
||||
cfg.ACME.AuthURL = lego.LEDirectoryStaging
|
||||
default:
|
||||
cfg.ACME.AuthURL = lego.LEDirectoryStaging
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/cert"
|
||||
"git.paulbsd.com/paulbsd/pki/src/config"
|
||||
"git.paulbsd.com/paulbsd/pki/src/domain"
|
||||
"git.paulbsd.com/paulbsd/pki/src/pki"
|
||||
_ "github.com/lib/pq"
|
||||
"xorm.io/xorm"
|
||||
@ -17,7 +18,7 @@ import (
|
||||
func Init(cfg *config.Config) (err error) {
|
||||
var databaseEngine = "postgres"
|
||||
tables := []interface{}{cert.Entry{},
|
||||
pki.User{}}
|
||||
pki.User{}, domain.Domain{}}
|
||||
|
||||
cfg.Db, err = xorm.NewEngine(databaseEngine,
|
||||
fmt.Sprintf("%s://%s:%s@%s/%s",
|
||||
|
12
src/domain/main.go
Normal file
12
src/domain/main.go
Normal file
@ -0,0 +1,12 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
// Domain describes a domain
|
||||
type Domain struct {
|
||||
ID int `xorm:"pk autoincr"`
|
||||
Domain string `xorm:"text notnull unique(domain_provider)"`
|
||||
Provider string `xorm:"text notnull unique(domain_provider)"`
|
||||
Created time.Time `xorm:"created notnull"`
|
||||
Updated time.Time `xorm:"updated notnull"`
|
||||
}
|
@ -9,13 +9,13 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/cert"
|
||||
"git.paulbsd.com/paulbsd/pki/src/config"
|
||||
"git.paulbsd.com/paulbsd/pki/src/domain"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
)
|
||||
@ -30,13 +30,10 @@ func (u *User) Init(cfg *config.Config) (err error) {
|
||||
}
|
||||
|
||||
// GetEntry returns requested acme ressource in database relative to domain
|
||||
func (u *User) GetEntry(cfg *config.Config, domains []string) (Entry cert.Entry, err error) {
|
||||
requireddate := time.Now().AddDate(0, 0, -cfg.ACME.MaxDaysBefore).Format("2006-01-02")
|
||||
|
||||
has, err := cfg.Db.Where("domains = ?", strings.Join(domains, ",")).Where(
|
||||
"validity_begin >= now()").Where(
|
||||
"validity_end <= ?::timestamp", requireddate).Where(
|
||||
"auth_url = ?", cfg.ACME.AuthURL).Desc(
|
||||
func (u *User) GetEntry(cfg *config.Config, domain *string) (Entry cert.Entry, err error) {
|
||||
has, err := cfg.Db.Where("domain = ?", domain).And(
|
||||
"auth_url = ?", cfg.ACME.AuthURL).And(
|
||||
fmt.Sprintf("validity_end::timestamp-'%d DAY'::INTERVAL >= now()", cfg.ACME.MaxDaysBefore)).Desc(
|
||||
"id").Get(&Entry)
|
||||
|
||||
if !has {
|
||||
@ -69,12 +66,38 @@ func (u *User) HandleRegistration(cfg *config.Config, client *lego.Client) (err
|
||||
}
|
||||
|
||||
// RequestNewCert returns a newly requested certificate to letsencrypt
|
||||
func (u *User) RequestNewCert(cfg *config.Config, domains []string) (certificates *certificate.Resource, err error) {
|
||||
func (u *User) RequestNewCert(cfg *config.Config, domainnames *[]string) (certs *certificate.Resource, err error) {
|
||||
legoconfig := lego.NewConfig(u)
|
||||
legoconfig.CADirURL = cfg.ACME.AuthURL
|
||||
legoconfig.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
ovhprovider, err := initProvider(cfg)
|
||||
var dom domain.Domain
|
||||
var has bool
|
||||
for _, d := range *domainnames {
|
||||
dom = domain.Domain{Domain: d}
|
||||
if has, err = cfg.Db.Get(&dom); has {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
if !has {
|
||||
err = fmt.Errorf("supplied domain not in allowed domains")
|
||||
return
|
||||
}
|
||||
|
||||
var provider challenge.Provider
|
||||
|
||||
switch dom.Provider {
|
||||
case "ovh":
|
||||
provider, err = initOVHProvider(cfg)
|
||||
case "pdns":
|
||||
provider, err = initPowerDNSProvider(cfg)
|
||||
default:
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
@ -84,7 +107,7 @@ func (u *User) RequestNewCert(cfg *config.Config, domains []string) (certificate
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
err = client.Challenge.SetDNS01Provider(ovhprovider)
|
||||
err = client.Challenge.SetDNS01Provider(provider)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
@ -98,14 +121,15 @@ func (u *User) RequestNewCert(cfg *config.Config, domains []string) (certificate
|
||||
}
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: domains,
|
||||
Domains: *domainnames,
|
||||
Bundle: true,
|
||||
}
|
||||
|
||||
certificates, err = client.Certificate.Obtain(request)
|
||||
certs, err = client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
package pki
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/config"
|
||||
"github.com/go-acme/lego/v4/providers/dns/ovh"
|
||||
"github.com/go-acme/lego/v4/providers/dns/pdns"
|
||||
)
|
||||
|
||||
// initProvider initialize DNS provider configuration
|
||||
func initProvider(cfg *config.Config) (ovhprovider *ovh.DNSProvider, err error) {
|
||||
// initOVHProvider initialize DNS provider configuration
|
||||
func initOVHProvider(cfg *config.Config) (ovhprovider *ovh.DNSProvider, err error) {
|
||||
ovhconfig := ovh.NewDefaultConfig()
|
||||
|
||||
ovhconfig.APIEndpoint = cfg.ACME.ProviderOptions["ovhendpoint"]
|
||||
@ -15,6 +19,24 @@ func initProvider(cfg *config.Config) (ovhprovider *ovh.DNSProvider, err error)
|
||||
ovhconfig.ConsumerKey = cfg.ACME.ProviderOptions["ovhck"]
|
||||
|
||||
ovhprovider, err = ovh.NewDNSProviderConfig(ovhconfig)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// initPowerDNSProvider initialize DNS provider configuration
|
||||
func initPowerDNSProvider(cfg *config.Config) (pdnsprovider *pdns.DNSProvider, err error) {
|
||||
pdnsconfig := pdns.NewDefaultConfig()
|
||||
|
||||
pdnsconfig.Host, err = url.Parse(cfg.ACME.ProviderOptions["pdnsapiurl"])
|
||||
pdnsconfig.APIKey = cfg.ACME.ProviderOptions["pdnsapikey"]
|
||||
|
||||
pdnsprovider, err = pdns.NewDNSProviderConfig(pdnsconfig)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/config"
|
||||
"git.paulbsd.com/paulbsd/pki/src/pki"
|
||||
@ -30,13 +29,18 @@ func RunServer(cfg *config.Config) (err error) {
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Welcome to PKI software (https://git.paulbsd.com/paulbsd/pki)")
|
||||
})
|
||||
e.GET("/domain/:domains", func(c echo.Context) (err error) {
|
||||
var result EntryResponse
|
||||
var domains = strings.Split(c.Param("domains"), ",")
|
||||
e.POST("/cert", func(c echo.Context) (err error) {
|
||||
var request = new(EntryRequest)
|
||||
var result = make(map[string]EntryResponse)
|
||||
err = c.Bind(&request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return c.JSON(http.StatusInternalServerError, "error parsing request")
|
||||
}
|
||||
|
||||
log.Println(fmt.Sprintf("Providing %s to user %s at %s", domains, c.Get("username"), c.RealIP()))
|
||||
log.Printf("Providing %s to user %s at %s\n", request.Domains, c.Get("username"), c.RealIP())
|
||||
|
||||
result, err = GetCertificate(cfg, c.Get("user").(*pki.User), domains)
|
||||
result, err = GetCertificate(cfg, c.Get("user").(*pki.User), &request.Domains)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, fmt.Sprintf("%s", err))
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/cert"
|
||||
@ -14,18 +13,24 @@ import (
|
||||
"git.paulbsd.com/paulbsd/pki/src/pki"
|
||||
)
|
||||
|
||||
const timeformatstring string = "2006-01-02 15:04:05"
|
||||
|
||||
var domainRegex, err = regexp.Compile(`^[a-z0-9\*]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$`)
|
||||
|
||||
// GetCertificate get certificate from database if exists, of request it from ACME
|
||||
func GetCertificate(cfg *config.Config, user *pki.User, domains []string) (result EntryResponse, err error) {
|
||||
func GetCertificate(cfg *config.Config, user *pki.User, domains *[]string) (result map[string]EntryResponse, err error) {
|
||||
err = CheckDomains(domains)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result = make(map[string]EntryResponse)
|
||||
|
||||
entry, err := user.GetEntry(cfg, domains)
|
||||
firstdomain := (*domains)[0]
|
||||
entry, err := user.GetEntry(cfg, &firstdomain)
|
||||
if err != nil {
|
||||
certs, err := user.RequestNewCert(cfg, domains)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error fetching new certificate %s", err))
|
||||
log.Printf("Error fetching new certificate %s\n", err)
|
||||
return result, err
|
||||
}
|
||||
NotBefore, NotAfter, err := GetDates(certs.Certificate)
|
||||
@ -33,37 +38,40 @@ func GetCertificate(cfg *config.Config, user *pki.User, domains []string) (resul
|
||||
log.Println("Error where parsing dates")
|
||||
return result, err
|
||||
}
|
||||
entry := cert.Entry{Domains: strings.Join(domains, ","),
|
||||
entry := cert.Entry{Domain: certs.Domain,
|
||||
Certificate: string(certs.Certificate),
|
||||
PrivateKey: string(certs.PrivateKey),
|
||||
ValidityBegin: NotBefore,
|
||||
ValidityEnd: NotAfter,
|
||||
AuthURL: cfg.ACME.AuthURL}
|
||||
cfg.Db.Insert(&entry)
|
||||
result = convertEntryToResponse(entry)
|
||||
result[firstdomain] = convertEntryToResponse(entry)
|
||||
return result, err
|
||||
}
|
||||
result = convertEntryToResponse(entry)
|
||||
result[firstdomain] = convertEntryToResponse(entry)
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDomains check if requested domains are valid
|
||||
func CheckDomains(domains []string) (err error) {
|
||||
domainRegex, err := regexp.Compile(`^[a-z0-9\*]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$`)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, d := range domains {
|
||||
res := domainRegex.Match([]byte(d))
|
||||
if !res {
|
||||
return fmt.Errorf(fmt.Sprintf("Domain %s has not a valid syntax %s, please verify", d, err))
|
||||
func CheckDomains(domains *[]string) (err error) {
|
||||
for _, domain := range *domains {
|
||||
err = CheckDomain(&domain)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDomain check if requested domain are valid
|
||||
func CheckDomain(domain *string) (err error) {
|
||||
res := domainRegex.Match([]byte(*domain))
|
||||
if !res {
|
||||
return fmt.Errorf("Domain %s has not a valid syntax %s, please verify", *domain, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDates decodes NotBefore and NotAfter date of cert
|
||||
func GetDates(cert []byte) (NotBefore time.Time, NotAfter time.Time, err error) {
|
||||
block, _ := pem.Decode(cert)
|
||||
@ -80,9 +88,7 @@ func GetDates(cert []byte) (NotBefore time.Time, NotAfter time.Time, err error)
|
||||
|
||||
// convertEntryToResponse converts database ACME entry to JSON ACME entry
|
||||
func convertEntryToResponse(in cert.Entry) (out EntryResponse) {
|
||||
timeformatstring := "2006-01-02 15:04:05"
|
||||
|
||||
out.Domains = in.Domains
|
||||
out.Domains = append(out.Domains, in.Domain)
|
||||
out.Certificate = in.Certificate
|
||||
out.PrivateKey = in.PrivateKey
|
||||
out.ValidityBegin = in.ValidityBegin.Format(timeformatstring)
|
||||
@ -91,11 +97,16 @@ func convertEntryToResponse(in cert.Entry) (out EntryResponse) {
|
||||
return
|
||||
}
|
||||
|
||||
// EntryRequest
|
||||
type EntryRequest struct {
|
||||
Domains []string `json:"domains"`
|
||||
}
|
||||
|
||||
// EntryResponse is the struct defining JSON response from webservice
|
||||
type EntryResponse struct {
|
||||
Domains string `json:"domains"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"privatekey"`
|
||||
ValidityBegin string `json:"validitybegin"`
|
||||
ValidityEnd string `json:"validityend"`
|
||||
Domains []string `json:"domains"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"privatekey"`
|
||||
ValidityBegin string `json:"validitybegin"`
|
||||
ValidityEnd string `json:"validityend"`
|
||||
}
|
||||
|
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
@ -1,10 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.13
|
||||
- 1.x
|
||||
- tip
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
4
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
4
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
@ -1,4 +1,4 @@
|
||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
|
||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls]
|
||||
|
||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
||||
|
||||
@ -21,8 +21,6 @@ Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
|
||||
|
||||
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
|
||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
||||
[travis]: https://travis-ci.org/cenkalti/backoff
|
||||
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
|
||||
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
||||
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
||||
|
||||
|
6
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
6
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
@ -57,10 +57,6 @@ func (b *backOffContext) NextBackOff() time.Duration {
|
||||
case <-b.ctx.Done():
|
||||
return Stop
|
||||
default:
|
||||
return b.BackOff.NextBackOff()
|
||||
}
|
||||
next := b.BackOff.NextBackOff()
|
||||
if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { // nolint: gosimple
|
||||
return Stop
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
60
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
60
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
@ -71,6 +71,9 @@ type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options.
|
||||
type ExponentialBackOffOpts func(*ExponentialBackOff)
|
||||
|
||||
// Default values for ExponentialBackOff.
|
||||
const (
|
||||
DefaultInitialInterval = 500 * time.Millisecond
|
||||
@ -81,7 +84,7 @@ const (
|
||||
)
|
||||
|
||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
||||
func NewExponentialBackOff() *ExponentialBackOff {
|
||||
func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
|
||||
b := &ExponentialBackOff{
|
||||
InitialInterval: DefaultInitialInterval,
|
||||
RandomizationFactor: DefaultRandomizationFactor,
|
||||
@ -91,10 +94,62 @@ func NewExponentialBackOff() *ExponentialBackOff {
|
||||
Stop: Stop,
|
||||
Clock: SystemClock,
|
||||
}
|
||||
for _, fn := range opts {
|
||||
fn(b)
|
||||
}
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
// WithInitialInterval sets the initial interval between retries.
|
||||
func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.InitialInterval = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithRandomizationFactor sets the randomization factor to add jitter to intervals.
|
||||
func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.RandomizationFactor = randomizationFactor
|
||||
}
|
||||
}
|
||||
|
||||
// WithMultiplier sets the multiplier for increasing the interval after each retry.
|
||||
func WithMultiplier(multiplier float64) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Multiplier = multiplier
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxInterval sets the maximum interval between retries.
|
||||
func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.MaxInterval = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxElapsedTime sets the maximum total time for retries.
|
||||
func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.MaxElapsedTime = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithRetryStopDuration sets the duration after which retries should stop.
|
||||
func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Stop = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithClockProvider sets the clock used to measure time.
|
||||
func WithClockProvider(clock Clock) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Clock = clock
|
||||
}
|
||||
}
|
||||
|
||||
type systemClock struct{}
|
||||
|
||||
func (t systemClock) Now() time.Time {
|
||||
@ -147,6 +202,9 @@ func (b *ExponentialBackOff) incrementCurrentInterval() {
|
||||
// Returns a random value from the following interval:
|
||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||
if randomizationFactor == 0 {
|
||||
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
||||
}
|
||||
var delta = randomizationFactor * float64(currentInterval)
|
||||
var minInterval = float64(currentInterval) - delta
|
||||
var maxInterval = float64(currentInterval) + delta
|
||||
|
3
vendor/github.com/cenkalti/backoff/v4/go.mod
generated
vendored
3
vendor/github.com/cenkalti/backoff/v4/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
||||
module github.com/cenkalti/backoff/v4
|
||||
|
||||
go 1.13
|
52
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
52
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
@ -5,10 +5,20 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData().
|
||||
// The operation will be retried using a backoff policy if it returns an error.
|
||||
type OperationWithData[T any] func() (T, error)
|
||||
|
||||
// An Operation is executing by Retry() or RetryNotify().
|
||||
// The operation will be retried using a backoff policy if it returns an error.
|
||||
type Operation func() error
|
||||
|
||||
func (o Operation) withEmptyData() OperationWithData[struct{}] {
|
||||
return func() (struct{}, error) {
|
||||
return struct{}{}, o()
|
||||
}
|
||||
}
|
||||
|
||||
// Notify is a notify-on-error function. It receives an operation error and
|
||||
// backoff delay if the operation failed (with an error).
|
||||
//
|
||||
@ -28,18 +38,41 @@ func Retry(o Operation, b BackOff) error {
|
||||
return RetryNotify(o, b, nil)
|
||||
}
|
||||
|
||||
// RetryWithData is like Retry but returns data in the response too.
|
||||
func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) {
|
||||
return RetryNotifyWithData(o, b, nil)
|
||||
}
|
||||
|
||||
// RetryNotify calls notify function with the error and wait duration
|
||||
// for each failed attempt before sleep.
|
||||
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
||||
return RetryNotifyWithTimer(operation, b, notify, nil)
|
||||
}
|
||||
|
||||
// RetryNotifyWithData is like RetryNotify but returns data in the response too.
|
||||
func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) {
|
||||
return doRetryNotify(operation, b, notify, nil)
|
||||
}
|
||||
|
||||
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
|
||||
// for each failed attempt before sleep.
|
||||
// A default timer that uses system timer is used when nil is passed.
|
||||
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
|
||||
var err error
|
||||
var next time.Duration
|
||||
_, err := doRetryNotify(operation.withEmptyData(), b, notify, t)
|
||||
return err
|
||||
}
|
||||
|
||||
// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too.
|
||||
func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||
return doRetryNotify(operation, b, notify, t)
|
||||
}
|
||||
|
||||
func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||
var (
|
||||
err error
|
||||
next time.Duration
|
||||
res T
|
||||
)
|
||||
if t == nil {
|
||||
t = &defaultTimer{}
|
||||
}
|
||||
@ -52,17 +85,22 @@ func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer
|
||||
|
||||
b.Reset()
|
||||
for {
|
||||
if err = operation(); err == nil {
|
||||
return nil
|
||||
res, err = operation()
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var permanent *PermanentError
|
||||
if errors.As(err, &permanent) {
|
||||
return permanent.Err
|
||||
return res, permanent.Err
|
||||
}
|
||||
|
||||
if next = b.NextBackOff(); next == Stop {
|
||||
return err
|
||||
if cerr := ctx.Err(); cerr != nil {
|
||||
return res, cerr
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
if notify != nil {
|
||||
@ -73,7 +111,7 @@ func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
return res, ctx.Err()
|
||||
case <-t.C():
|
||||
}
|
||||
}
|
||||
|
13
vendor/github.com/dgrijalva/jwt-go/.travis.yml
generated
vendored
13
vendor/github.com/dgrijalva/jwt-go/.travis.yml
generated
vendored
@ -1,13 +0,0 @@
|
||||
language: go
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- tip
|
97
vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
generated
vendored
97
vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
generated
vendored
@ -1,97 +0,0 @@
|
||||
## Migration Guide from v2 -> v3
|
||||
|
||||
Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code.
|
||||
|
||||
### `Token.Claims` is now an interface type
|
||||
|
||||
The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`.
|
||||
|
||||
`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property.
|
||||
|
||||
The old example for parsing a token looked like this..
|
||||
|
||||
```go
|
||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
is now directly mapped to...
|
||||
|
||||
```go
|
||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type.
|
||||
|
||||
```go
|
||||
type MyCustomClaims struct {
|
||||
User string
|
||||
*StandardClaims
|
||||
}
|
||||
|
||||
if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(*MyCustomClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt)
|
||||
}
|
||||
```
|
||||
|
||||
### `ParseFromRequest` has been moved
|
||||
|
||||
To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`.
|
||||
|
||||
`Extractors` do the work of picking the token string out of a request. The interface is simple and composable.
|
||||
|
||||
This simple parsing example:
|
||||
|
||||
```go
|
||||
if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil {
|
||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
is directly mapped to:
|
||||
|
||||
```go
|
||||
if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
There are several concrete `Extractor` types provided for your convenience:
|
||||
|
||||
* `HeaderExtractor` will search a list of headers until one contains content.
|
||||
* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content.
|
||||
* `MultiExtractor` will try a list of `Extractors` in order until one returns content.
|
||||
* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token.
|
||||
* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument
|
||||
* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header
|
||||
|
||||
|
||||
### RSA signing methods no longer accept `[]byte` keys
|
||||
|
||||
Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse.
|
||||
|
||||
To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types.
|
||||
|
||||
```go
|
||||
func keyLookupFunc(*Token) (interface{}, error) {
|
||||
// Don't forget to validate the alg is what you expect:
|
||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
|
||||
// Look up key
|
||||
key, err := lookupPublicKey(token.Header["kid"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unpack key from PEM encoded PKCS8
|
||||
return jwt.ParseRSAPublicKeyFromPEM(key)
|
||||
}
|
||||
```
|
2
vendor/github.com/go-acme/lego/v4/acme/api/account.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/acme/api/account.go
generated
vendored
@ -16,7 +16,7 @@ func (a *AccountService) New(req acme.Account) (acme.ExtendedAccount, error) {
|
||||
resp, err := a.core.post(a.core.GetDirectory().NewAccountURL, req, &account)
|
||||
location := getLocation(resp)
|
||||
|
||||
if len(location) > 0 {
|
||||
if location != "" {
|
||||
a.core.jws.SetKid(location)
|
||||
}
|
||||
|
||||
|
12
vendor/github.com/go-acme/lego/v4/acme/api/api.go
generated
vendored
12
vendor/github.com/go-acme/lego/v4/acme/api/api.go
generated
vendored
@ -2,7 +2,6 @@ package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@ -71,7 +70,7 @@ func (a *Core) post(uri string, reqBody, response interface{}) (*http.Response,
|
||||
}
|
||||
|
||||
// postAsGet performs an HTTP POST ("POST-as-GET") request.
|
||||
// https://tools.ietf.org/html/rfc8555#section-6.3
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-6.3
|
||||
func (a *Core) postAsGet(uri string, response interface{}) (*http.Response, error) {
|
||||
return a.retrievablePost(uri, []byte{}, response)
|
||||
}
|
||||
@ -83,8 +82,6 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
||||
bo.MaxInterval = 5 * time.Second
|
||||
bo.MaxElapsedTime = 20 * time.Second
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
var resp *http.Response
|
||||
operation := func() error {
|
||||
var err error
|
||||
@ -96,8 +93,7 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
||||
return err
|
||||
}
|
||||
|
||||
cancel()
|
||||
return err
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -107,7 +103,7 @@ func (a *Core) retrievablePost(uri string, content []byte, response interface{})
|
||||
log.Infof("retry due to: %v", err)
|
||||
}
|
||||
|
||||
err := backoff.RetryNotify(operation, backoff.WithContext(bo, ctx), notify)
|
||||
err := backoff.RetryNotify(operation, bo, notify)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@ -121,7 +117,7 @@ func (a *Core) signedPost(uri string, content []byte, response interface{}) (*ht
|
||||
return nil, fmt.Errorf("failed to post JWS message: failed to sign content: %w", err)
|
||||
}
|
||||
|
||||
signedBody := bytes.NewBuffer([]byte(signedContent.FullSerialize()))
|
||||
signedBody := bytes.NewBufferString(signedContent.FullSerialize())
|
||||
|
||||
resp, err := a.doer.Post(uri, signedBody, "application/jose+json", response)
|
||||
|
||||
|
14
vendor/github.com/go-acme/lego/v4/acme/api/certificate.go
generated
vendored
14
vendor/github.com/go-acme/lego/v4/acme/api/certificate.go
generated
vendored
@ -1,10 +1,11 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
@ -39,7 +40,7 @@ func (c *CertificateService) GetAll(certURL string, bundle bool) (map[string]*ac
|
||||
certs := map[string]*acme.RawCertificate{certURL: cert}
|
||||
|
||||
// URLs of "alternate" link relation
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.4.2
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4.2
|
||||
alts := getLinks(headers, "alternate")
|
||||
|
||||
for _, alt := range alts {
|
||||
@ -71,7 +72,7 @@ func (c *CertificateService) get(certURL string, bundle bool) (*acme.RawCertific
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
data, err := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
if err != nil {
|
||||
return nil, resp.Header, err
|
||||
}
|
||||
@ -87,12 +88,17 @@ func (c *CertificateService) getCertificateChain(cert []byte, headers http.Heade
|
||||
// See https://community.letsencrypt.org/t/acme-v2-no-up-link-in-response/64962
|
||||
_, issuer := pem.Decode(cert)
|
||||
if issuer != nil {
|
||||
// If bundle is false, we want to return a single certificate.
|
||||
// To do this, we remove the issuer cert(s) from the issued cert.
|
||||
if !bundle {
|
||||
cert = bytes.TrimSuffix(cert, issuer)
|
||||
}
|
||||
return &acme.RawCertificate{Cert: cert, Issuer: issuer}
|
||||
}
|
||||
|
||||
// The issuer certificate link may be supplied via an "up" link
|
||||
// in the response headers of a new certificate.
|
||||
// See https://tools.ietf.org/html/rfc8555#section-7.4.2
|
||||
// See https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4.2
|
||||
up := getLink(headers, "up")
|
||||
|
||||
issuer, err := c.getIssuerFromLink(up)
|
||||
|
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/nonces/nonce_manager.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/nonces/nonce_manager.go
generated
vendored
@ -63,7 +63,7 @@ func (n *Manager) getNonce() (string, error) {
|
||||
return GetFromResponse(resp)
|
||||
}
|
||||
|
||||
// GetFromResponse Extracts a nonce from a HTTP response.
|
||||
// GetFromResponse Extracts a nonce from an HTTP response.
|
||||
func GetFromResponse(resp *http.Response) (string, error) {
|
||||
if resp == nil {
|
||||
return "", errors.New("nil response")
|
||||
|
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/secure/jws.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/secure/jws.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme/api/internal/nonces"
|
||||
jose "gopkg.in/square/go-jose.v2"
|
||||
jose "github.com/go-jose/go-jose/v4"
|
||||
)
|
||||
|
||||
// JWS Represents a JWS.
|
||||
|
9
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/sender.go
generated
vendored
9
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/sender.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -96,7 +95,7 @@ func (d *Doer) do(req *http.Request, response interface{}) (*http.Response, erro
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
raw, err := ioutil.ReadAll(resp.Body)
|
||||
raw, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@ -120,7 +119,7 @@ func (d *Doer) formatUserAgent() string {
|
||||
|
||||
func checkError(req *http.Request, resp *http.Response) error {
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%d :: %s :: %s :: %w", resp.StatusCode, req.Method, req.URL, err)
|
||||
}
|
||||
@ -134,6 +133,10 @@ func checkError(req *http.Request, resp *http.Response) error {
|
||||
errorDetails.Method = req.Method
|
||||
errorDetails.URL = req.URL.String()
|
||||
|
||||
if errorDetails.HTTPStatus == 0 {
|
||||
errorDetails.HTTPStatus = resp.StatusCode
|
||||
}
|
||||
|
||||
// Check for errors we handle specifically
|
||||
if errorDetails.HTTPStatus == http.StatusBadRequest && errorDetails.Type == acme.BadNonceErr {
|
||||
return &acme.NonceError{ProblemDetails: errorDetails}
|
||||
|
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/useragent.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/acme/api/internal/sender/useragent.go
generated
vendored
@ -5,7 +5,7 @@ package sender
|
||||
|
||||
const (
|
||||
// ourUserAgent is the User-Agent of this underlying library package.
|
||||
ourUserAgent = "xenolf-acme/4.3.1"
|
||||
ourUserAgent = "xenolf-acme/4.17.4"
|
||||
|
||||
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
|
||||
// values: detach|release
|
||||
|
39
vendor/github.com/go-acme/lego/v4/acme/api/order.go
generated
vendored
39
vendor/github.com/go-acme/lego/v4/acme/api/order.go
generated
vendored
@ -3,21 +3,58 @@ package api
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
)
|
||||
|
||||
// OrderOptions used to create an order (optional).
|
||||
type OrderOptions struct {
|
||||
NotBefore time.Time
|
||||
NotAfter time.Time
|
||||
// A string uniquely identifying a previously-issued certificate which this
|
||||
// order is intended to replace.
|
||||
// - https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-5
|
||||
ReplacesCertID string
|
||||
}
|
||||
|
||||
type OrderService service
|
||||
|
||||
// New Creates a new order.
|
||||
func (o *OrderService) New(domains []string) (acme.ExtendedOrder, error) {
|
||||
return o.NewWithOptions(domains, nil)
|
||||
}
|
||||
|
||||
// NewWithOptions Creates a new order.
|
||||
func (o *OrderService) NewWithOptions(domains []string, opts *OrderOptions) (acme.ExtendedOrder, error) {
|
||||
var identifiers []acme.Identifier
|
||||
for _, domain := range domains {
|
||||
identifiers = append(identifiers, acme.Identifier{Type: "dns", Value: domain})
|
||||
ident := acme.Identifier{Value: domain, Type: "dns"}
|
||||
|
||||
if net.ParseIP(domain) != nil {
|
||||
ident.Type = "ip"
|
||||
}
|
||||
|
||||
identifiers = append(identifiers, ident)
|
||||
}
|
||||
|
||||
orderReq := acme.Order{Identifiers: identifiers}
|
||||
|
||||
if opts != nil {
|
||||
if !opts.NotAfter.IsZero() {
|
||||
orderReq.NotAfter = opts.NotAfter.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
if !opts.NotBefore.IsZero() {
|
||||
orderReq.NotBefore = opts.NotBefore.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
if o.core.GetDirectory().RenewalInfo != "" {
|
||||
orderReq.Replaces = opts.ReplacesCertID
|
||||
}
|
||||
}
|
||||
|
||||
var order acme.Order
|
||||
resp, err := o.core.post(o.core.GetDirectory().NewOrderURL, orderReq, &order)
|
||||
if err != nil {
|
||||
|
28
vendor/github.com/go-acme/lego/v4/acme/api/renewal.go
generated
vendored
Normal file
28
vendor/github.com/go-acme/lego/v4/acme/api/renewal.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ErrNoARI is returned when the server does not advertise a renewal info endpoint.
|
||||
var ErrNoARI = errors.New("renewalInfo[get/post]: server does not advertise a renewal info endpoint")
|
||||
|
||||
// GetRenewalInfo GETs renewal information for a certificate from the renewalInfo endpoint.
|
||||
// This is used to determine if a certificate needs to be renewed.
|
||||
//
|
||||
// Note: this endpoint is part of a draft specification, not all ACME servers will implement it.
|
||||
// This method will return api.ErrNoARI if the server does not advertise a renewal info endpoint.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-acme-ari
|
||||
func (c *CertificateService) GetRenewalInfo(certID string) (*http.Response, error) {
|
||||
if c.core.GetDirectory().RenewalInfo == "" {
|
||||
return nil, ErrNoARI
|
||||
}
|
||||
|
||||
if certID == "" {
|
||||
return nil, errors.New("renewalInfo[get]: 'certID' cannot be empty")
|
||||
}
|
||||
|
||||
return c.core.HTTPClient.Get(c.core.GetDirectory().RenewalInfo + "/" + certID)
|
||||
}
|
108
vendor/github.com/go-acme/lego/v4/acme/commons.go
generated
vendored
108
vendor/github.com/go-acme/lego/v4/acme/commons.go
generated
vendored
@ -1,5 +1,5 @@
|
||||
// Package acme contains all objects related the ACME endpoints.
|
||||
// https://tools.ietf.org/html/rfc8555
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html
|
||||
package acme
|
||||
|
||||
import (
|
||||
@ -7,20 +7,38 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Challenge statuses.
|
||||
// https://tools.ietf.org/html/rfc8555#section-7.1.6
|
||||
// ACME status values of Account, Order, Authorization and Challenge objects.
|
||||
// See https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.6 for details.
|
||||
const (
|
||||
StatusPending = "pending"
|
||||
StatusInvalid = "invalid"
|
||||
StatusValid = "valid"
|
||||
StatusProcessing = "processing"
|
||||
StatusDeactivated = "deactivated"
|
||||
StatusExpired = "expired"
|
||||
StatusInvalid = "invalid"
|
||||
StatusPending = "pending"
|
||||
StatusProcessing = "processing"
|
||||
StatusReady = "ready"
|
||||
StatusRevoked = "revoked"
|
||||
StatusUnknown = "unknown"
|
||||
StatusValid = "valid"
|
||||
)
|
||||
|
||||
// CRL reason codes as defined in RFC 5280.
|
||||
// https://datatracker.ietf.org/doc/html/rfc5280#section-5.3.1
|
||||
const (
|
||||
CRLReasonUnspecified uint = 0
|
||||
CRLReasonKeyCompromise uint = 1
|
||||
CRLReasonCACompromise uint = 2
|
||||
CRLReasonAffiliationChanged uint = 3
|
||||
CRLReasonSuperseded uint = 4
|
||||
CRLReasonCessationOfOperation uint = 5
|
||||
CRLReasonCertificateHold uint = 6
|
||||
CRLReasonRemoveFromCRL uint = 8
|
||||
CRLReasonPrivilegeWithdrawn uint = 9
|
||||
CRLReasonAACompromise uint = 10
|
||||
)
|
||||
|
||||
// Directory the ACME directory object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.1
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
|
||||
// - https://datatracker.ietf.org/doc/draft-ietf-acme-ari/
|
||||
type Directory struct {
|
||||
NewNonceURL string `json:"newNonce"`
|
||||
NewAccountURL string `json:"newAccount"`
|
||||
@ -29,10 +47,11 @@ type Directory struct {
|
||||
RevokeCertURL string `json:"revokeCert"`
|
||||
KeyChangeURL string `json:"keyChange"`
|
||||
Meta Meta `json:"meta"`
|
||||
RenewalInfo string `json:"renewalInfo"`
|
||||
}
|
||||
|
||||
// Meta the ACME meta object (related to Directory).
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.1
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
|
||||
type Meta struct {
|
||||
// termsOfService (optional, string):
|
||||
// A URL identifying the current terms of service.
|
||||
@ -52,12 +71,12 @@ type Meta struct {
|
||||
|
||||
// externalAccountRequired (optional, boolean):
|
||||
// If this field is present and set to "true",
|
||||
// then the CA requires that all new- account requests include an "externalAccountBinding" field
|
||||
// then the CA requires that all new-account requests include an "externalAccountBinding" field
|
||||
// associating the new account with an external account.
|
||||
ExternalAccountRequired bool `json:"externalAccountRequired"`
|
||||
}
|
||||
|
||||
// ExtendedAccount a extended Account.
|
||||
// ExtendedAccount an extended Account.
|
||||
type ExtendedAccount struct {
|
||||
Account
|
||||
// Contains the value of the response header `Location`
|
||||
@ -65,14 +84,14 @@ type ExtendedAccount struct {
|
||||
}
|
||||
|
||||
// Account the ACME account Object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.2
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.3
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.2
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3
|
||||
type Account struct {
|
||||
// status (required, string):
|
||||
// The status of this account.
|
||||
// Possible values are: "valid", "deactivated", and "revoked".
|
||||
// The value "deactivated" should be used to indicate client-initiated deactivation
|
||||
// whereas "revoked" should be used to indicate server- initiated deactivation. (See Section 7.1.6)
|
||||
// whereas "revoked" should be used to indicate server-initiated deactivation. (See Section 7.1.6)
|
||||
Status string `json:"status,omitempty"`
|
||||
|
||||
// contact (optional, array of string):
|
||||
@ -112,7 +131,7 @@ type ExtendedOrder struct {
|
||||
}
|
||||
|
||||
// Order the ACME order Object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.3
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.3
|
||||
type Order struct {
|
||||
// status (required, string):
|
||||
// The status of this order.
|
||||
@ -162,10 +181,16 @@ type Order struct {
|
||||
// certificate (optional, string):
|
||||
// A URL for the certificate that has been issued in response to this order
|
||||
Certificate string `json:"certificate,omitempty"`
|
||||
|
||||
// replaces (optional, string):
|
||||
// replaces (string, optional): A string uniquely identifying a
|
||||
// previously-issued certificate which this order is intended to replace.
|
||||
// - https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-5
|
||||
Replaces string `json:"replaces,omitempty"`
|
||||
}
|
||||
|
||||
// Authorization the ACME authorization object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.4
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
|
||||
type Authorization struct {
|
||||
// status (required, string):
|
||||
// The status of this authorization.
|
||||
@ -207,8 +232,8 @@ type ExtendedChallenge struct {
|
||||
}
|
||||
|
||||
// Challenge the ACME challenge object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.1.5
|
||||
// - https://tools.ietf.org/html/rfc8555#section-8
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.5
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-8
|
||||
type Challenge struct {
|
||||
// type (required, string):
|
||||
// The type of challenge encoded in the object.
|
||||
@ -241,23 +266,23 @@ type Challenge struct {
|
||||
// It MUST NOT contain any characters outside the base64url alphabet,
|
||||
// and MUST NOT include base64 padding characters ("=").
|
||||
// See [RFC4086] for additional information on randomness requirements.
|
||||
// https://tools.ietf.org/html/rfc8555#section-8.3
|
||||
// https://tools.ietf.org/html/rfc8555#section-8.4
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.3
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.4
|
||||
Token string `json:"token"`
|
||||
|
||||
// https://tools.ietf.org/html/rfc8555#section-8.1
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-8.1
|
||||
KeyAuthorization string `json:"keyAuthorization"`
|
||||
}
|
||||
|
||||
// Identifier the ACME identifier object.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-9.7.7
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-9.7.7
|
||||
type Identifier struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// CSRMessage Certificate Signing Request.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.4
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
|
||||
type CSRMessage struct {
|
||||
// csr (required, string):
|
||||
// A CSR encoding the parameters for the certificate being requested [RFC2986].
|
||||
@ -267,8 +292,8 @@ type CSRMessage struct {
|
||||
}
|
||||
|
||||
// RevokeCertMessage a certificate revocation message.
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.6
|
||||
// - https://tools.ietf.org/html/rfc5280#section-5.3.1
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.6
|
||||
// - https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1
|
||||
type RevokeCertMessage struct {
|
||||
// certificate (required, string):
|
||||
// The certificate to be revoked, in the base64url-encoded version of the DER format.
|
||||
@ -289,3 +314,36 @@ type RawCertificate struct {
|
||||
Cert []byte
|
||||
Issuer []byte
|
||||
}
|
||||
|
||||
// Window is a window of time.
|
||||
type Window struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
}
|
||||
|
||||
// RenewalInfoResponse is the response to GET requests made the renewalInfo endpoint.
|
||||
// - (4.1. Getting Renewal Information) https://datatracker.ietf.org/doc/draft-ietf-acme-ari/
|
||||
type RenewalInfoResponse struct {
|
||||
// SuggestedWindow contains two fields, start and end,
|
||||
// whose values are timestamps which bound the window of time in which the CA recommends renewing the certificate.
|
||||
SuggestedWindow Window `json:"suggestedWindow"`
|
||||
// ExplanationURL is an optional URL pointing to a page which may explain why the suggested renewal window is what it is.
|
||||
// For example, it may be a page explaining the CA's dynamic load-balancing strategy,
|
||||
// or a page documenting which certificates are affected by a mass revocation event.
|
||||
// Callers SHOULD provide this URL to their operator, if present.
|
||||
ExplanationURL string `json:"explanationURL"`
|
||||
}
|
||||
|
||||
// RenewalInfoUpdateRequest is the JWS payload for POST requests made to the renewalInfo endpoint.
|
||||
// - (4.2. RenewalInfo Objects) https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-4.2
|
||||
type RenewalInfoUpdateRequest struct {
|
||||
// CertID is a composite string in the format: base64url(AKI) || '.' || base64url(Serial), where AKI is the
|
||||
// certificate's authority key identifier and Serial is the certificate's serial number. For details, see:
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-4.1
|
||||
CertID string `json:"certID"`
|
||||
// Replaced is required and indicates whether or not the client considers the certificate to have been replaced.
|
||||
// A certificate is considered replaced when its revocation would not disrupt any ongoing services,
|
||||
// for instance because it has been renewed and the new certificate is in use, or because it is no longer in use.
|
||||
// Clients SHOULD NOT send a request where this value is false.
|
||||
Replaced bool `json:"replaced"`
|
||||
}
|
||||
|
6
vendor/github.com/go-acme/lego/v4/acme/errors.go
generated
vendored
6
vendor/github.com/go-acme/lego/v4/acme/errors.go
generated
vendored
@ -11,8 +11,8 @@ const (
|
||||
)
|
||||
|
||||
// ProblemDetails the problem details object.
|
||||
// - https://tools.ietf.org/html/rfc7807#section-3.1
|
||||
// - https://tools.ietf.org/html/rfc8555#section-7.3.3
|
||||
// - https://www.rfc-editor.org/rfc/rfc7807.html#section-3.1
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3.3
|
||||
type ProblemDetails struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
@ -26,7 +26,7 @@ type ProblemDetails struct {
|
||||
}
|
||||
|
||||
// SubProblem a "subproblems".
|
||||
// - https://tools.ietf.org/html/rfc8555#section-6.7.1
|
||||
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-6.7.1
|
||||
type SubProblem struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
|
80
vendor/github.com/go-acme/lego/v4/certcrypto/crypto.go
generated
vendored
80
vendor/github.com/go-acme/lego/v4/certcrypto/crypto.go
generated
vendored
@ -14,6 +14,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -25,6 +27,7 @@ const (
|
||||
EC256 = KeyType("P256")
|
||||
EC384 = KeyType("P384")
|
||||
RSA2048 = KeyType("2048")
|
||||
RSA3072 = KeyType("3072")
|
||||
RSA4096 = KeyType("4096")
|
||||
RSA8192 = KeyType("8192")
|
||||
)
|
||||
@ -82,9 +85,12 @@ func ParsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
|
||||
// ParsePEMPrivateKey parses a private key from key, which is a PEM block.
|
||||
// Borrowed from Go standard library, to handle various private key and PEM block types.
|
||||
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L291-L308
|
||||
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238)
|
||||
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238
|
||||
func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
|
||||
keyBlockDER, _ := pem.Decode(key)
|
||||
if keyBlockDER == nil {
|
||||
return nil, errors.New("invalid PEM block")
|
||||
}
|
||||
|
||||
if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") {
|
||||
return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type)
|
||||
@ -118,6 +124,8 @@ func GeneratePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
|
||||
return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
case RSA2048:
|
||||
return rsa.GenerateKey(rand.Reader, 2048)
|
||||
case RSA3072:
|
||||
return rsa.GenerateKey(rand.Reader, 3072)
|
||||
case RSA4096:
|
||||
return rsa.GenerateKey(rand.Reader, 4096)
|
||||
case RSA8192:
|
||||
@ -128,9 +136,20 @@ func GeneratePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
|
||||
}
|
||||
|
||||
func GenerateCSR(privateKey crypto.PrivateKey, domain string, san []string, mustStaple bool) ([]byte, error) {
|
||||
var dnsNames []string
|
||||
var ipAddresses []net.IP
|
||||
for _, altname := range san {
|
||||
if ip := net.ParseIP(altname); ip != nil {
|
||||
ipAddresses = append(ipAddresses, ip)
|
||||
} else {
|
||||
dnsNames = append(dnsNames, altname)
|
||||
}
|
||||
}
|
||||
|
||||
template := x509.CertificateRequest{
|
||||
Subject: pkix.Name{CommonName: domain},
|
||||
DNSNames: san,
|
||||
Subject: pkix.Name{CommonName: domain},
|
||||
DNSNames: dnsNames,
|
||||
IPAddresses: ipAddresses,
|
||||
}
|
||||
|
||||
if mustStaple {
|
||||
@ -179,7 +198,7 @@ func PemDecodeTox509CSR(data []byte) (*x509.CertificateRequest, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pemBlock.Type != "CERTIFICATE REQUEST" {
|
||||
if pemBlock.Type != "CERTIFICATE REQUEST" && pemBlock.Type != "NEW CERTIFICATE REQUEST" {
|
||||
return nil, errors.New("PEM block is not a certificate request")
|
||||
}
|
||||
|
||||
@ -198,6 +217,26 @@ func ParsePEMCertificate(cert []byte) (*x509.Certificate, error) {
|
||||
return x509.ParseCertificate(pemBlock.Bytes)
|
||||
}
|
||||
|
||||
func GetCertificateMainDomain(cert *x509.Certificate) (string, error) {
|
||||
return getMainDomain(cert.Subject, cert.DNSNames)
|
||||
}
|
||||
|
||||
func GetCSRMainDomain(cert *x509.CertificateRequest) (string, error) {
|
||||
return getMainDomain(cert.Subject, cert.DNSNames)
|
||||
}
|
||||
|
||||
func getMainDomain(subject pkix.Name, dnsNames []string) (string, error) {
|
||||
if subject.CommonName == "" && len(dnsNames) == 0 {
|
||||
return "", errors.New("missing domain")
|
||||
}
|
||||
|
||||
if subject.CommonName != "" {
|
||||
return subject.CommonName, nil
|
||||
}
|
||||
|
||||
return dnsNames[0], nil
|
||||
}
|
||||
|
||||
func ExtractDomains(cert *x509.Certificate) []string {
|
||||
var domains []string
|
||||
if cert.Subject.CommonName != "" {
|
||||
@ -212,6 +251,13 @@ func ExtractDomains(cert *x509.Certificate) []string {
|
||||
domains = append(domains, sanDomain)
|
||||
}
|
||||
|
||||
commonNameIP := net.ParseIP(cert.Subject.CommonName)
|
||||
for _, sanIP := range cert.IPAddresses {
|
||||
if !commonNameIP.Equal(sanIP) {
|
||||
domains = append(domains, sanIP.String())
|
||||
}
|
||||
}
|
||||
|
||||
return domains
|
||||
}
|
||||
|
||||
@ -223,7 +269,7 @@ func ExtractDomainsCSR(csr *x509.CertificateRequest) []string {
|
||||
|
||||
// loop over the SubjectAltName DNS names
|
||||
for _, sanName := range csr.DNSNames {
|
||||
if containsSAN(domains, sanName) {
|
||||
if slices.Contains(domains, sanName) {
|
||||
// Duplicate; skip this name
|
||||
continue
|
||||
}
|
||||
@ -232,16 +278,14 @@ func ExtractDomainsCSR(csr *x509.CertificateRequest) []string {
|
||||
domains = append(domains, sanName)
|
||||
}
|
||||
|
||||
return domains
|
||||
}
|
||||
|
||||
func containsSAN(domains []string, sanName string) bool {
|
||||
for _, existingName := range domains {
|
||||
if existingName == sanName {
|
||||
return true
|
||||
cnip := net.ParseIP(csr.Subject.CommonName)
|
||||
for _, sanIP := range csr.IPAddresses {
|
||||
if !cnip.Equal(sanIP) {
|
||||
domains = append(domains, sanIP.String())
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
return domains
|
||||
}
|
||||
|
||||
func GeneratePemCert(privateKey *rsa.PrivateKey, domain string, extensions []pkix.Extension) ([]byte, error) {
|
||||
@ -261,7 +305,7 @@ func generateDerCert(privateKey *rsa.PrivateKey, expiration time.Time, domain st
|
||||
}
|
||||
|
||||
if expiration.IsZero() {
|
||||
expiration = time.Now().Add(365)
|
||||
expiration = time.Now().AddDate(1, 0, 0)
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
@ -274,9 +318,15 @@ func generateDerCert(privateKey *rsa.PrivateKey, expiration time.Time, domain st
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment,
|
||||
BasicConstraintsValid: true,
|
||||
DNSNames: []string{domain},
|
||||
ExtraExtensions: extensions,
|
||||
}
|
||||
|
||||
// handling SAN filling as type suspected
|
||||
if ip := net.ParseIP(domain); ip != nil {
|
||||
template.IPAddresses = []net.IP{ip}
|
||||
} else {
|
||||
template.DNSNames = []string{domain}
|
||||
}
|
||||
|
||||
return x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
|
||||
}
|
||||
|
19
vendor/github.com/go-acme/lego/v4/certificate/authorization.go
generated
vendored
19
vendor/github.com/go-acme/lego/v4/certificate/authorization.go
generated
vendored
@ -12,6 +12,7 @@ const (
|
||||
// limited on the "new-reg", "new-authz" and "new-cert" endpoints.
|
||||
// From the documentation the limitation is 20 requests per second,
|
||||
// but using 20 as value doesn't work but 18 do.
|
||||
// https://letsencrypt.org/docs/rate-limits/
|
||||
overallRequestLimit = 18
|
||||
)
|
||||
|
||||
@ -35,13 +36,14 @@ func (c *Certifier) getAuthorizations(order acme.ExtendedOrder) ([]acme.Authoriz
|
||||
}
|
||||
|
||||
var responses []acme.Authorization
|
||||
failures := make(obtainError)
|
||||
for i := 0; i < len(order.Authorizations); i++ {
|
||||
|
||||
failures := newObtainError()
|
||||
for range len(order.Authorizations) {
|
||||
select {
|
||||
case res := <-resc:
|
||||
responses = append(responses, res)
|
||||
case err := <-errc:
|
||||
failures[err.Domain] = err.Error
|
||||
failures.Add(err.Domain, err.Error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,15 +54,10 @@ 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) {
|
||||
func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder, force bool) {
|
||||
for _, authzURL := range order.Authorizations {
|
||||
auth, err := c.core.Authorizations.Get(authzURL)
|
||||
if err != nil {
|
||||
@ -68,7 +65,7 @@ func (c *Certifier) deactivateAuthorizations(order acme.ExtendedOrder) {
|
||||
continue
|
||||
}
|
||||
|
||||
if auth.Status == acme.StatusValid {
|
||||
if auth.Status == acme.StatusValid && !force {
|
||||
log.Infof("Skipping deactivating of valid auth: %s", authzURL)
|
||||
continue
|
||||
}
|
||||
|
200
vendor/github.com/go-acme/lego/v4/certificate/certificates.go
generated
vendored
200
vendor/github.com/go-acme/lego/v4/certificate/certificates.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -49,22 +49,44 @@ type Resource struct {
|
||||
// If you do not want that you can supply your own private key in the privateKey parameter.
|
||||
// If this parameter is non-nil it will be used instead of generating a new one.
|
||||
//
|
||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
||||
// If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
|
||||
//
|
||||
// If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
|
||||
// See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
|
||||
type ObtainRequest struct {
|
||||
Domains []string
|
||||
Bundle bool
|
||||
PrivateKey crypto.PrivateKey
|
||||
MustStaple bool
|
||||
PreferredChain string
|
||||
Domains []string
|
||||
PrivateKey crypto.PrivateKey
|
||||
MustStaple bool
|
||||
|
||||
NotBefore time.Time
|
||||
NotAfter time.Time
|
||||
Bundle bool
|
||||
PreferredChain string
|
||||
AlwaysDeactivateAuthorizations bool
|
||||
// A string uniquely identifying a previously-issued certificate which this
|
||||
// order is intended to replace.
|
||||
// - https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-5
|
||||
ReplacesCertID string
|
||||
}
|
||||
|
||||
// ObtainForCSRRequest The request to obtain a certificate matching the CSR passed into it.
|
||||
//
|
||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
||||
// If `Bundle` is true, the `[]byte` contains both the issuer certificate and your issued certificate as a bundle.
|
||||
//
|
||||
// If `AlwaysDeactivateAuthorizations` is true, the authorizations are also relinquished if the obtain request was successful.
|
||||
// See https://datatracker.ietf.org/doc/html/rfc8555#section-7.5.2.
|
||||
type ObtainForCSRRequest struct {
|
||||
CSR *x509.CertificateRequest
|
||||
Bundle bool
|
||||
PreferredChain string
|
||||
CSR *x509.CertificateRequest
|
||||
|
||||
NotBefore time.Time
|
||||
NotAfter time.Time
|
||||
Bundle bool
|
||||
PreferredChain string
|
||||
AlwaysDeactivateAuthorizations bool
|
||||
// A string uniquely identifying a previously-issued certificate which this
|
||||
// order is intended to replace.
|
||||
// - https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-5
|
||||
ReplacesCertID string
|
||||
}
|
||||
|
||||
type resolver interface {
|
||||
@ -109,7 +131,13 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
|
||||
log.Infof("[%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
|
||||
}
|
||||
|
||||
order, err := c.core.Orders.New(domains)
|
||||
orderOpts := &api.OrderOptions{
|
||||
NotBefore: request.NotBefore,
|
||||
NotAfter: request.NotAfter,
|
||||
ReplacesCertID: request.ReplacesCertID,
|
||||
}
|
||||
|
||||
order, err := c.core.Orders.NewWithOptions(domains, orderOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -117,33 +145,32 @@ func (c *Certifier) Obtain(request ObtainRequest) (*Resource, error) {
|
||||
authz, err := c.getAuthorizations(order)
|
||||
if err != nil {
|
||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||
c.deactivateAuthorizations(order)
|
||||
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = c.resolver.Solve(authz)
|
||||
if err != nil {
|
||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||
c.deactivateAuthorizations(order)
|
||||
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Do not return an empty failures map, because
|
||||
// it would still be a non-nil error value
|
||||
if len(failures) > 0 {
|
||||
return cert, failures
|
||||
if request.AlwaysDeactivateAuthorizations {
|
||||
c.deactivateAuthorizations(order, true)
|
||||
}
|
||||
return cert, nil
|
||||
|
||||
return cert, failures.Join()
|
||||
}
|
||||
|
||||
// ObtainForCSR tries to obtain a certificate matching the CSR passed into it.
|
||||
@ -170,7 +197,13 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
|
||||
log.Infof("[%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
|
||||
}
|
||||
|
||||
order, err := c.core.Orders.New(domains)
|
||||
orderOpts := &api.OrderOptions{
|
||||
NotBefore: request.NotBefore,
|
||||
NotAfter: request.NotAfter,
|
||||
ReplacesCertID: request.ReplacesCertID,
|
||||
}
|
||||
|
||||
order, err := c.core.Orders.NewWithOptions(domains, orderOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -178,38 +211,37 @@ func (c *Certifier) ObtainForCSR(request ObtainForCSRRequest) (*Resource, error)
|
||||
authz, err := c.getAuthorizations(order)
|
||||
if err != nil {
|
||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||
c.deactivateAuthorizations(order)
|
||||
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = c.resolver.Solve(authz)
|
||||
if err != nil {
|
||||
// If any challenge fails, return. Do not generate partial SAN certificates.
|
||||
c.deactivateAuthorizations(order)
|
||||
c.deactivateAuthorizations(order, request.AlwaysDeactivateAuthorizations)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if request.AlwaysDeactivateAuthorizations {
|
||||
c.deactivateAuthorizations(order, true)
|
||||
}
|
||||
|
||||
if cert != nil {
|
||||
// Add the CSR to the certificate so that it can be used for renewals.
|
||||
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) {
|
||||
@ -221,16 +253,23 @@ func (c *Certifier) getForOrder(domains []string, order acme.ExtendedOrder, bund
|
||||
}
|
||||
}
|
||||
|
||||
// Determine certificate name(s) based on the authorization resources
|
||||
commonName := domains[0]
|
||||
commonName := ""
|
||||
if len(domains[0]) <= 64 {
|
||||
commonName = domains[0]
|
||||
}
|
||||
|
||||
// RFC8555 Section 7.4 "Applying for Certificate Issuance"
|
||||
// https://tools.ietf.org/html/rfc8555#section-7.4
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
|
||||
// says:
|
||||
// Clients SHOULD NOT make any assumptions about the sort order of
|
||||
// "identifiers" or "authorizations" elements in the returned order
|
||||
// object.
|
||||
san := []string{commonName}
|
||||
|
||||
var san []string
|
||||
if commonName != "" {
|
||||
san = append(san, commonName)
|
||||
}
|
||||
|
||||
for _, auth := range order.Identifiers {
|
||||
if auth.Value != commonName {
|
||||
san = append(san, auth.Value)
|
||||
@ -252,15 +291,14 @@ func (c *Certifier) getForCSR(domains []string, order acme.ExtendedOrder, bundle
|
||||
return nil, err
|
||||
}
|
||||
|
||||
commonName := domains[0]
|
||||
certRes := &Resource{
|
||||
Domain: commonName,
|
||||
Domain: domains[0],
|
||||
CertURL: respOrder.Certificate,
|
||||
PrivateKey: privateKeyPem,
|
||||
}
|
||||
|
||||
if respOrder.Status == acme.StatusValid {
|
||||
// if the certificate is available right away, short cut!
|
||||
// if the certificate is available right away, shortcut!
|
||||
ok, errR := c.checkResponse(respOrder, certRes, bundle, preferredChain)
|
||||
if errR != nil {
|
||||
return nil, errR
|
||||
@ -349,6 +387,11 @@ func (c *Certifier) checkResponse(order acme.ExtendedOrder, certRes *Resource, b
|
||||
|
||||
// Revoke takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
|
||||
func (c *Certifier) Revoke(cert []byte) error {
|
||||
return c.RevokeWithReason(cert, nil)
|
||||
}
|
||||
|
||||
// RevokeWithReason takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
|
||||
func (c *Certifier) RevokeWithReason(cert []byte, reason *uint) error {
|
||||
certificates, err := certcrypto.ParsePEMBundle(cert)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -361,11 +404,24 @@ func (c *Certifier) Revoke(cert []byte) error {
|
||||
|
||||
revokeMsg := acme.RevokeCertMessage{
|
||||
Certificate: base64.RawURLEncoding.EncodeToString(x509Cert.Raw),
|
||||
Reason: reason,
|
||||
}
|
||||
|
||||
return c.core.Certificates.Revoke(revokeMsg)
|
||||
}
|
||||
|
||||
// RenewOptions options used by Certifier.RenewWithOptions.
|
||||
type RenewOptions struct {
|
||||
NotBefore time.Time
|
||||
NotAfter time.Time
|
||||
// If true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
||||
Bundle bool
|
||||
PreferredChain string
|
||||
AlwaysDeactivateAuthorizations bool
|
||||
// Not supported for CSR request.
|
||||
MustStaple bool
|
||||
}
|
||||
|
||||
// Renew takes a Resource and tries to renew the certificate.
|
||||
//
|
||||
// If the renewal process succeeds, the new certificate will be returned in a new CertResource.
|
||||
@ -376,7 +432,26 @@ func (c *Certifier) Revoke(cert []byte) error {
|
||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
||||
//
|
||||
// For private key reuse the PrivateKey property of the passed in Resource should be non-nil.
|
||||
// Deprecated: use RenewWithOptions instead.
|
||||
func (c *Certifier) Renew(certRes Resource, bundle, mustStaple bool, preferredChain string) (*Resource, error) {
|
||||
return c.RenewWithOptions(certRes, &RenewOptions{
|
||||
Bundle: bundle,
|
||||
PreferredChain: preferredChain,
|
||||
MustStaple: mustStaple,
|
||||
})
|
||||
}
|
||||
|
||||
// RenewWithOptions takes a Resource and tries to renew the certificate.
|
||||
//
|
||||
// If the renewal process succeeds, the new certificate will be returned in a new CertResource.
|
||||
// Please be aware that this function will return a new certificate in ANY case that is not an error.
|
||||
// If the server does not provide us with a new cert on a GET request to the CertURL
|
||||
// this function will start a new-cert flow where a new certificate gets generated.
|
||||
//
|
||||
// If bundle is true, the []byte contains both the issuer certificate and your issued certificate as a bundle.
|
||||
//
|
||||
// For private key reuse the PrivateKey property of the passed in Resource should be non-nil.
|
||||
func (c *Certifier) RenewWithOptions(certRes Resource, options *RenewOptions) (*Resource, error) {
|
||||
// Input certificate is PEM encoded.
|
||||
// Decode it here as we may need the decoded cert later on in the renewal process.
|
||||
// The input may be a bundle or a single certificate.
|
||||
@ -403,11 +478,17 @@ func (c *Certifier) Renew(certRes Resource, bundle, mustStaple bool, preferredCh
|
||||
return nil, errP
|
||||
}
|
||||
|
||||
return c.ObtainForCSR(ObtainForCSRRequest{
|
||||
CSR: csr,
|
||||
Bundle: bundle,
|
||||
PreferredChain: preferredChain,
|
||||
})
|
||||
request := ObtainForCSRRequest{CSR: csr}
|
||||
|
||||
if options != nil {
|
||||
request.NotBefore = options.NotBefore
|
||||
request.NotAfter = options.NotAfter
|
||||
request.Bundle = options.Bundle
|
||||
request.PreferredChain = options.PreferredChain
|
||||
request.AlwaysDeactivateAuthorizations = options.AlwaysDeactivateAuthorizations
|
||||
}
|
||||
|
||||
return c.ObtainForCSR(request)
|
||||
}
|
||||
|
||||
var privateKey crypto.PrivateKey
|
||||
@ -418,13 +499,21 @@ func (c *Certifier) Renew(certRes Resource, bundle, mustStaple bool, preferredCh
|
||||
}
|
||||
}
|
||||
|
||||
query := ObtainRequest{
|
||||
request := ObtainRequest{
|
||||
Domains: certcrypto.ExtractDomains(x509Cert),
|
||||
Bundle: bundle,
|
||||
PrivateKey: privateKey,
|
||||
MustStaple: mustStaple,
|
||||
}
|
||||
return c.Obtain(query)
|
||||
|
||||
if options != nil {
|
||||
request.MustStaple = options.MustStaple
|
||||
request.NotBefore = options.NotBefore
|
||||
request.NotAfter = options.NotAfter
|
||||
request.Bundle = options.Bundle
|
||||
request.PreferredChain = options.PreferredChain
|
||||
request.AlwaysDeactivateAuthorizations = options.AlwaysDeactivateAuthorizations
|
||||
}
|
||||
|
||||
return c.Obtain(request)
|
||||
}
|
||||
|
||||
// GetOCSP takes a PEM encoded cert or cert bundle returning the raw OCSP response,
|
||||
@ -465,7 +554,7 @@ func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
issuerBytes, errC := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
issuerBytes, errC := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
if errC != nil {
|
||||
return nil, nil, errC
|
||||
}
|
||||
@ -494,7 +583,7 @@ func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
ocspResBytes, err := ioutil.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
ocspResBytes, err := io.ReadAll(http.MaxBytesReader(nil, resp.Body, maxBodySize))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -525,8 +614,13 @@ func (c *Certifier) Get(url string, bundle bool) (*Resource, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domain, err := certcrypto.GetCertificateMainDomain(x509Certs[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Resource{
|
||||
Domain: x509Certs[0].Subject.CommonName,
|
||||
Domain: domain,
|
||||
Certificate: cert,
|
||||
IssuerCertificate: issuer,
|
||||
CertURL: url,
|
||||
@ -560,11 +654,11 @@ func checkOrderStatus(order acme.ExtendedOrder) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc8555#section-7.1.4
|
||||
// https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
|
||||
// The domain name MUST be encoded in the form in which it would appear in a certificate.
|
||||
// That is, it MUST be encoded according to the rules in Section 7 of [RFC5280].
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc5280#section-7
|
||||
// https://www.rfc-editor.org/rfc/rfc5280.html#section-7
|
||||
func sanitizeDomain(domains []string) []string {
|
||||
var sanitizedDomains []string
|
||||
for _, domain := range domains {
|
||||
|
36
vendor/github.com/go-acme/lego/v4/certificate/errors.go
generated
vendored
36
vendor/github.com/go-acme/lego/v4/certificate/errors.go
generated
vendored
@ -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 {
|
||||
buffer.WriteString(fmt.Sprintf("[%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 {
|
||||
|
129
vendor/github.com/go-acme/lego/v4/certificate/renewal.go
generated
vendored
Normal file
129
vendor/github.com/go-acme/lego/v4/certificate/renewal.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
package certificate
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
)
|
||||
|
||||
// RenewalInfoRequest contains the necessary renewal information.
|
||||
type RenewalInfoRequest struct {
|
||||
Cert *x509.Certificate
|
||||
}
|
||||
|
||||
// RenewalInfoResponse is a wrapper around acme.RenewalInfoResponse that provides a method for determining when to renew a certificate.
|
||||
type RenewalInfoResponse struct {
|
||||
acme.RenewalInfoResponse
|
||||
|
||||
// RetryAfter header indicating the polling interval that the ACME server recommends.
|
||||
// Conforming clients SHOULD query the renewalInfo URL again after the RetryAfter period has passed,
|
||||
// as the server may provide a different suggestedWindow.
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-03#section-4.2
|
||||
RetryAfter time.Duration
|
||||
}
|
||||
|
||||
// ShouldRenewAt determines the optimal renewal time based on the current time (UTC),renewal window suggest by ARI, and the client's willingness to sleep.
|
||||
// It returns a pointer to a time.Time value indicating when the renewal should be attempted or nil if deferred until the next normal wake time.
|
||||
// This method implements the RECOMMENDED algorithm described in draft-ietf-acme-ari.
|
||||
//
|
||||
// - (4.1-11. Getting Renewal Information) https://datatracker.ietf.org/doc/draft-ietf-acme-ari/
|
||||
func (r *RenewalInfoResponse) ShouldRenewAt(now time.Time, willingToSleep time.Duration) *time.Time {
|
||||
// Explicitly convert all times to UTC.
|
||||
now = now.UTC()
|
||||
start := r.SuggestedWindow.Start.UTC()
|
||||
end := r.SuggestedWindow.End.UTC()
|
||||
|
||||
// Select a uniform random time within the suggested window.
|
||||
window := end.Sub(start)
|
||||
randomDuration := time.Duration(rand.Int63n(int64(window)))
|
||||
rt := start.Add(randomDuration)
|
||||
|
||||
// If the selected time is in the past, attempt renewal immediately.
|
||||
if rt.Before(now) {
|
||||
return &now
|
||||
}
|
||||
|
||||
// Otherwise, if the client can schedule itself to attempt renewal at exactly the selected time, do so.
|
||||
willingToSleepUntil := now.Add(willingToSleep)
|
||||
if willingToSleepUntil.After(rt) || willingToSleepUntil.Equal(rt) {
|
||||
return &rt
|
||||
}
|
||||
|
||||
// TODO: Otherwise, if the selected time is before the next time that the client would wake up normally, attempt renewal immediately.
|
||||
|
||||
// Otherwise, sleep until the next normal wake time, re-check ARI, and return to Step 1.
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRenewalInfo sends a request to the ACME server's renewalInfo endpoint to obtain a suggested renewal window.
|
||||
// The caller MUST provide the certificate and issuer certificate for the certificate they wish to renew.
|
||||
// The caller should attempt to renew the certificate at the time indicated by the ShouldRenewAt method of the returned RenewalInfoResponse object.
|
||||
//
|
||||
// Note: this endpoint is part of a draft specification, not all ACME servers will implement it.
|
||||
// This method will return api.ErrNoARI if the server does not advertise a renewal info endpoint.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-acme-ari
|
||||
func (c *Certifier) GetRenewalInfo(req RenewalInfoRequest) (*RenewalInfoResponse, error) {
|
||||
certID, err := MakeARICertID(req.Cert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making certID: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.core.Certificates.GetRenewalInfo(certID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var info RenewalInfoResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if retry := resp.Header.Get("Retry-After"); retry != "" {
|
||||
info.RetryAfter, err = time.ParseDuration(retry + "s")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// MakeARICertID constructs a certificate identifier as described in draft-ietf-acme-ari-03, section 4.1.
|
||||
func MakeARICertID(leaf *x509.Certificate) (string, error) {
|
||||
if leaf == nil {
|
||||
return "", errors.New("leaf certificate is nil")
|
||||
}
|
||||
|
||||
// Marshal the Serial Number into DER.
|
||||
der, err := asn1.Marshal(leaf.SerialNumber)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check if the DER encoded bytes are sufficient (at least 3 bytes: tag,
|
||||
// length, and value).
|
||||
if len(der) < 3 {
|
||||
return "", errors.New("invalid DER encoding of serial number")
|
||||
}
|
||||
|
||||
// Extract only the integer bytes from the DER encoded Serial Number
|
||||
// Skipping the first 2 bytes (tag and length).
|
||||
serial := base64.RawURLEncoding.EncodeToString(der[2:])
|
||||
|
||||
// Convert the Authority Key Identifier to base64url encoding without
|
||||
// padding.
|
||||
aki := base64.RawURLEncoding.EncodeToString(leaf.AuthorityKeyId)
|
||||
|
||||
// Construct the final identifier by concatenating AKI and Serial Number.
|
||||
return fmt.Sprintf("%s.%s", aki, serial), nil
|
||||
}
|
6
vendor/github.com/go-acme/lego/v4/challenge/challenges.go
generated
vendored
6
vendor/github.com/go-acme/lego/v4/challenge/challenges.go
generated
vendored
@ -10,15 +10,15 @@ import (
|
||||
type Type string
|
||||
|
||||
const (
|
||||
// HTTP01 is the "http-01" ACME challenge https://tools.ietf.org/html/rfc8555#section-8.3
|
||||
// HTTP01 is the "http-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8555.html#section-8.3
|
||||
// Note: ChallengePath returns the URL path to fulfill this challenge.
|
||||
HTTP01 = Type("http-01")
|
||||
|
||||
// DNS01 is the "dns-01" ACME challenge https://tools.ietf.org/html/rfc8555#section-8.4
|
||||
// DNS01 is the "dns-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8555.html#section-8.4
|
||||
// Note: GetRecord returns a DNS record which will fulfill this challenge.
|
||||
DNS01 = Type("dns-01")
|
||||
|
||||
// TLSALPN01 is the "tls-alpn-01" ACME challenge https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07
|
||||
// TLSALPN01 is the "tls-alpn-01" ACME challenge https://www.rfc-editor.org/rfc/rfc8737.html
|
||||
TLSALPN01 = Type("tls-alpn-01")
|
||||
)
|
||||
|
||||
|
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/cname.go
generated
vendored
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/cname.go
generated
vendored
@ -1,12 +1,16 @@
|
||||
package dns01
|
||||
|
||||
import "github.com/miekg/dns"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Update FQDN with CNAME if any.
|
||||
func updateDomainWithCName(r *dns.Msg, fqdn string) string {
|
||||
for _, rr := range r.Answer {
|
||||
if cn, ok := rr.(*dns.CNAME); ok {
|
||||
if cn.Hdr.Name == fqdn {
|
||||
if strings.EqualFold(cn.Hdr.Name, fqdn) {
|
||||
return cn.Target
|
||||
}
|
||||
}
|
||||
|
73
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge.go
generated
vendored
73
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
@ -114,7 +115,7 @@ func (c *Challenge) Solve(authz acme.Authorization) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fqdn, value := GetRecord(authz.Identifier.Value, keyAuth)
|
||||
info := GetChallengeInfo(authz.Identifier.Value, keyAuth)
|
||||
|
||||
var timeout, interval time.Duration
|
||||
switch provider := c.provider.(type) {
|
||||
@ -124,12 +125,12 @@ func (c *Challenge) Solve(authz acme.Authorization) error {
|
||||
timeout, interval = DefaultPropagationTimeout, DefaultPollingInterval
|
||||
}
|
||||
|
||||
log.Infof("[%s] acme: Checking DNS record propagation using %+v", domain, recursiveNameservers)
|
||||
log.Infof("[%s] acme: Checking DNS record propagation. [nameservers=%s]", domain, strings.Join(recursiveNameservers, ","))
|
||||
|
||||
time.Sleep(interval)
|
||||
|
||||
err = wait.For("propagation", timeout, interval, func() (bool, error) {
|
||||
stop, errP := c.preCheck.call(domain, fqdn, value)
|
||||
stop, errP := c.preCheck.call(domain, info.EffectiveFQDN, info.Value)
|
||||
if !stop || errP != nil {
|
||||
log.Infof("[%s] acme: Waiting for DNS record propagation.", domain)
|
||||
}
|
||||
@ -172,19 +173,67 @@ type sequential interface {
|
||||
}
|
||||
|
||||
// GetRecord returns a DNS record which will fulfill the `dns-01` challenge.
|
||||
// Deprecated: use GetChallengeInfo instead.
|
||||
func GetRecord(domain, keyAuth string) (fqdn, value string) {
|
||||
info := GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
return info.EffectiveFQDN, info.Value
|
||||
}
|
||||
|
||||
// ChallengeInfo contains the information use to create the TXT record.
|
||||
type ChallengeInfo struct {
|
||||
// FQDN is the full-qualified challenge domain (i.e. `_acme-challenge.[domain].`)
|
||||
FQDN string
|
||||
|
||||
// EffectiveFQDN contains the resulting FQDN after the CNAMEs resolutions.
|
||||
EffectiveFQDN string
|
||||
|
||||
// Value contains the value for the TXT record.
|
||||
Value string
|
||||
}
|
||||
|
||||
// GetChallengeInfo returns information used to create a DNS record which will fulfill the `dns-01` challenge.
|
||||
func GetChallengeInfo(domain, keyAuth string) ChallengeInfo {
|
||||
keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
|
||||
// base64URL encoding without padding
|
||||
value = base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
|
||||
fqdn = fmt.Sprintf("_acme-challenge.%s.", domain)
|
||||
value := base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
|
||||
|
||||
if ok, _ := strconv.ParseBool(os.Getenv("LEGO_EXPERIMENTAL_CNAME_SUPPORT")); ok {
|
||||
r, err := dnsQuery(fqdn, dns.TypeCNAME, recursiveNameservers, true)
|
||||
// Check if the domain has CNAME then return that
|
||||
if err == nil && r.Rcode == dns.RcodeSuccess {
|
||||
fqdn = updateDomainWithCName(r, fqdn)
|
||||
}
|
||||
ok, _ := strconv.ParseBool(os.Getenv("LEGO_DISABLE_CNAME_SUPPORT"))
|
||||
|
||||
return ChallengeInfo{
|
||||
Value: value,
|
||||
FQDN: getChallengeFQDN(domain, false),
|
||||
EffectiveFQDN: getChallengeFQDN(domain, !ok),
|
||||
}
|
||||
}
|
||||
|
||||
func getChallengeFQDN(domain string, followCNAME bool) string {
|
||||
fqdn := fmt.Sprintf("_acme-challenge.%s.", domain)
|
||||
|
||||
if !followCNAME {
|
||||
return fqdn
|
||||
}
|
||||
|
||||
return
|
||||
// recursion counter so it doesn't spin out of control
|
||||
for range 50 {
|
||||
// Keep following CNAMEs
|
||||
r, err := dnsQuery(fqdn, dns.TypeCNAME, recursiveNameservers, true)
|
||||
|
||||
if err != nil || r.Rcode != dns.RcodeSuccess {
|
||||
// No more CNAME records to follow, exit
|
||||
break
|
||||
}
|
||||
|
||||
// Check if the domain has CNAME then use that
|
||||
cname := updateDomainWithCName(r, fqdn)
|
||||
if cname == fqdn {
|
||||
break
|
||||
}
|
||||
|
||||
log.Infof("Found CNAME entry for %q: %q", fqdn, cname)
|
||||
|
||||
fqdn = cname
|
||||
}
|
||||
|
||||
return fqdn
|
||||
}
|
||||
|
23
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge_manual.go
generated
vendored
23
vendor/github.com/go-acme/lego/v4/challenge/dns01/dns_challenge_manual.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
dnsTemplate = `%s %d IN TXT "%s"`
|
||||
dnsTemplate = `%s %d IN TXT %q`
|
||||
)
|
||||
|
||||
// DNSProviderManual is an implementation of the ChallengeProvider interface.
|
||||
@ -21,33 +21,36 @@ func NewDNSProviderManual() (*DNSProviderManual, error) {
|
||||
|
||||
// Present prints instructions for manually creating the TXT record.
|
||||
func (*DNSProviderManual) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := GetRecord(domain, keyAuth)
|
||||
info := GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := FindZoneByFqdn(fqdn)
|
||||
authZone, err := FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("manual: could not find zone: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("lego: Please create the following TXT record in your %s zone:\n", authZone)
|
||||
fmt.Printf(dnsTemplate+"\n", fqdn, DefaultTTL, value)
|
||||
fmt.Printf(dnsTemplate+"\n", info.EffectiveFQDN, DefaultTTL, info.Value)
|
||||
fmt.Printf("lego: Press 'Enter' when you are done\n")
|
||||
|
||||
_, err = bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||
if err != nil {
|
||||
return fmt.Errorf("manual: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp prints instructions for manually removing the TXT record.
|
||||
func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := GetRecord(domain, keyAuth)
|
||||
info := GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := FindZoneByFqdn(fqdn)
|
||||
authZone, err := FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("manual: could not find zone: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("lego: You can now remove this TXT record from your %s zone:\n", authZone)
|
||||
fmt.Printf(dnsTemplate+"\n", fqdn, DefaultTTL, "...")
|
||||
fmt.Printf(dnsTemplate+"\n", info.EffectiveFQDN, DefaultTTL, "...")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
24
vendor/github.com/go-acme/lego/v4/challenge/dns01/domain.go
generated
vendored
Normal file
24
vendor/github.com/go-acme/lego/v4/challenge/dns01/domain.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
package dns01
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// ExtractSubDomain extracts the subdomain part from a domain and a zone.
|
||||
func ExtractSubDomain(domain, zone string) (string, error) {
|
||||
canonDomain := dns.Fqdn(domain)
|
||||
canonZone := dns.Fqdn(zone)
|
||||
|
||||
if canonDomain == canonZone {
|
||||
return "", fmt.Errorf("no subdomain because the domain and the zone are identical: %s", canonDomain)
|
||||
}
|
||||
|
||||
if !dns.IsSubDomain(canonZone, canonDomain) {
|
||||
return "", fmt.Errorf("%s is not a subdomain of %s", canonDomain, canonZone)
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(canonDomain, "."+canonZone), nil
|
||||
}
|
155
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver.go
generated
vendored
155
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver.go
generated
vendored
@ -4,6 +4,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -13,9 +16,6 @@ import (
|
||||
|
||||
const defaultResolvConf = "/etc/resolv.conf"
|
||||
|
||||
// dnsTimeout is used to override the default DNS timeout of 10 seconds.
|
||||
var dnsTimeout = 10 * time.Second
|
||||
|
||||
var (
|
||||
fqdnSoaCache = map[string]*soaCacheEntry{}
|
||||
muFqdnSoaCache sync.Mutex
|
||||
@ -99,12 +99,12 @@ func lookupNameservers(fqdn string) ([]string, error) {
|
||||
|
||||
zone, err := FindZoneByFqdn(fqdn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine the zone: %w", err)
|
||||
return nil, fmt.Errorf("could not find zone: %w", err)
|
||||
}
|
||||
|
||||
r, err := dnsQuery(zone, dns.TypeNS, recursiveNameservers, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("NS call failed: %w", err)
|
||||
}
|
||||
|
||||
for _, rr := range r.Answer {
|
||||
@ -116,7 +116,8 @@ func lookupNameservers(fqdn string) ([]string, error) {
|
||||
if len(authoritativeNss) > 0 {
|
||||
return authoritativeNss, nil
|
||||
}
|
||||
return nil, errors.New("could not determine authoritative nameservers")
|
||||
|
||||
return nil, fmt.Errorf("[zone=%s] could not determine authoritative nameservers", zone)
|
||||
}
|
||||
|
||||
// FindPrimaryNsByFqdn determines the primary nameserver of the zone apex for the given fqdn
|
||||
@ -130,7 +131,7 @@ func FindPrimaryNsByFqdn(fqdn string) (string, error) {
|
||||
func FindPrimaryNsByFqdnCustom(fqdn string, nameservers []string) (string, error) {
|
||||
soa, err := lookupSoaByFqdn(fqdn, nameservers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("[fqdn=%s] %w", fqdn, err)
|
||||
}
|
||||
return soa.primaryNs, nil
|
||||
}
|
||||
@ -146,7 +147,7 @@ func FindZoneByFqdn(fqdn string) (string, error) {
|
||||
func FindZoneByFqdnCustom(fqdn string, nameservers []string) (string, error) {
|
||||
soa, err := lookupSoaByFqdn(fqdn, nameservers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("[fqdn=%s] %w", fqdn, err)
|
||||
}
|
||||
return soa.zone, nil
|
||||
}
|
||||
@ -171,35 +172,35 @@ func lookupSoaByFqdn(fqdn string, nameservers []string) (*soaCacheEntry, error)
|
||||
|
||||
func fetchSoaByFqdn(fqdn string, nameservers []string) (*soaCacheEntry, error) {
|
||||
var err error
|
||||
var in *dns.Msg
|
||||
var r *dns.Msg
|
||||
|
||||
labelIndexes := dns.Split(fqdn)
|
||||
for _, index := range labelIndexes {
|
||||
domain := fqdn[index:]
|
||||
|
||||
in, err = dnsQuery(domain, dns.TypeSOA, nameservers, true)
|
||||
r, err = dnsQuery(domain, dns.TypeSOA, nameservers, true)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if in == nil {
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
switch in.Rcode {
|
||||
switch r.Rcode {
|
||||
case dns.RcodeSuccess:
|
||||
// Check if we got a SOA RR in the answer section
|
||||
if len(in.Answer) == 0 {
|
||||
if len(r.Answer) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// CNAME records cannot/should not exist at the root of a zone.
|
||||
// So we skip a domain when a CNAME is found.
|
||||
if dnsMsgContainsCNAME(in) {
|
||||
if dnsMsgContainsCNAME(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ans := range in.Answer {
|
||||
for _, ans := range r.Answer {
|
||||
if soa, ok := ans.(*dns.SOA); ok {
|
||||
return newSoaCacheEntry(soa), nil
|
||||
}
|
||||
@ -208,36 +209,46 @@ func fetchSoaByFqdn(fqdn string, nameservers []string) (*soaCacheEntry, error) {
|
||||
// NXDOMAIN
|
||||
default:
|
||||
// Any response code other than NOERROR and NXDOMAIN is treated as error
|
||||
return nil, fmt.Errorf("unexpected response code '%s' for %s", dns.RcodeToString[in.Rcode], domain)
|
||||
return nil, &DNSError{Message: fmt.Sprintf("unexpected response for '%s'", domain), MsgOut: r}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("could not find the start of authority for %s%s", fqdn, formatDNSError(in, err))
|
||||
return nil, &DNSError{Message: fmt.Sprintf("could not find the start of authority for '%s'", fqdn), MsgOut: r, Err: err}
|
||||
}
|
||||
|
||||
// dnsMsgContainsCNAME checks for a CNAME answer in msg.
|
||||
func dnsMsgContainsCNAME(msg *dns.Msg) bool {
|
||||
for _, ans := range msg.Answer {
|
||||
if _, ok := ans.(*dns.CNAME); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.ContainsFunc(msg.Answer, func(rr dns.RR) bool {
|
||||
_, ok := rr.(*dns.CNAME)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func dnsQuery(fqdn string, rtype uint16, nameservers []string, recursive bool) (*dns.Msg, error) {
|
||||
m := createDNSMsg(fqdn, rtype, recursive)
|
||||
|
||||
var in *dns.Msg
|
||||
if len(nameservers) == 0 {
|
||||
return nil, &DNSError{Message: "empty list of nameservers"}
|
||||
}
|
||||
|
||||
var r *dns.Msg
|
||||
var err error
|
||||
var errAll error
|
||||
|
||||
for _, ns := range nameservers {
|
||||
in, err = sendDNSQuery(m, ns)
|
||||
if err == nil && len(in.Answer) > 0 {
|
||||
r, err = sendDNSQuery(m, ns)
|
||||
if err == nil && len(r.Answer) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
errAll = errors.Join(errAll, err)
|
||||
}
|
||||
return in, err
|
||||
|
||||
if err != nil {
|
||||
return r, errAll
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func createDNSMsg(fqdn string, rtype uint16, recursive bool) *dns.Msg {
|
||||
@ -253,32 +264,84 @@ func createDNSMsg(fqdn string, rtype uint16, recursive bool) *dns.Msg {
|
||||
}
|
||||
|
||||
func sendDNSQuery(m *dns.Msg, ns string) (*dns.Msg, error) {
|
||||
udp := &dns.Client{Net: "udp", Timeout: dnsTimeout}
|
||||
in, _, err := udp.Exchange(m, ns)
|
||||
|
||||
if in != nil && in.Truncated {
|
||||
if ok, _ := strconv.ParseBool(os.Getenv("LEGO_EXPERIMENTAL_DNS_TCP_ONLY")); ok {
|
||||
tcp := &dns.Client{Net: "tcp", Timeout: dnsTimeout}
|
||||
// If the TCP request succeeds, the err will reset to nil
|
||||
in, _, err = tcp.Exchange(m, ns)
|
||||
r, _, err := tcp.Exchange(m, ns)
|
||||
if err != nil {
|
||||
return r, &DNSError{Message: "DNS call error", MsgIn: m, NS: ns, Err: err}
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
return in, err
|
||||
}
|
||||
udp := &dns.Client{Net: "udp", Timeout: dnsTimeout}
|
||||
r, _, err := udp.Exchange(m, ns)
|
||||
|
||||
func formatDNSError(msg *dns.Msg, err error) string {
|
||||
var parts []string
|
||||
|
||||
if msg != nil {
|
||||
parts = append(parts, dns.RcodeToString[msg.Rcode])
|
||||
if r != nil && r.Truncated {
|
||||
tcp := &dns.Client{Net: "tcp", Timeout: dnsTimeout}
|
||||
// If the TCP request succeeds, the "err" will reset to nil
|
||||
r, _, err = tcp.Exchange(m, ns)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
parts = append(parts, err.Error())
|
||||
return r, &DNSError{Message: "DNS call error", MsgIn: m, NS: ns, Err: err}
|
||||
}
|
||||
|
||||
if len(parts) > 0 {
|
||||
return ": " + strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
return ""
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// DNSError error related to DNS calls.
|
||||
type DNSError struct {
|
||||
Message string
|
||||
NS string
|
||||
MsgIn *dns.Msg
|
||||
MsgOut *dns.Msg
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d *DNSError) Error() string {
|
||||
var details []string
|
||||
if d.NS != "" {
|
||||
details = append(details, "ns="+d.NS)
|
||||
}
|
||||
|
||||
if d.MsgIn != nil && len(d.MsgIn.Question) > 0 {
|
||||
details = append(details, fmt.Sprintf("question='%s'", formatQuestions(d.MsgIn.Question)))
|
||||
}
|
||||
|
||||
if d.MsgOut != nil {
|
||||
if d.MsgIn == nil || len(d.MsgIn.Question) == 0 {
|
||||
details = append(details, fmt.Sprintf("question='%s'", formatQuestions(d.MsgOut.Question)))
|
||||
}
|
||||
|
||||
details = append(details, "code="+dns.RcodeToString[d.MsgOut.Rcode])
|
||||
}
|
||||
|
||||
msg := "DNS error"
|
||||
if d.Message != "" {
|
||||
msg = d.Message
|
||||
}
|
||||
|
||||
if d.Err != nil {
|
||||
msg += ": " + d.Err.Error()
|
||||
}
|
||||
|
||||
if len(details) > 0 {
|
||||
msg += " [" + strings.Join(details, ", ") + "]"
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
func (d *DNSError) Unwrap() error {
|
||||
return d.Err
|
||||
}
|
||||
|
||||
func formatQuestions(questions []dns.Question) string {
|
||||
var parts []string
|
||||
for _, question := range questions {
|
||||
parts = append(parts, strings.ReplaceAll(strings.TrimPrefix(question.String(), ";"), "\t", " "))
|
||||
}
|
||||
|
||||
return strings.Join(parts, ";")
|
||||
}
|
||||
|
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_unix.go
generated
vendored
Normal file
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_unix.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build !windows
|
||||
|
||||
package dns01
|
||||
|
||||
import "time"
|
||||
|
||||
// dnsTimeout is used to override the default DNS timeout of 10 seconds.
|
||||
var dnsTimeout = 10 * time.Second
|
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_windows.go
generated
vendored
Normal file
8
vendor/github.com/go-acme/lego/v4/challenge/dns01/nameserver_windows.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build windows
|
||||
|
||||
package dns01
|
||||
|
||||
import "time"
|
||||
|
||||
// dnsTimeout is used to override the default DNS timeout of 20 seconds.
|
||||
var dnsTimeout = 20 * time.Second
|
13
vendor/github.com/go-acme/lego/v4/challenge/http01/domain_matcher.go
generated
vendored
13
vendor/github.com/go-acme/lego/v4/challenge/http01/domain_matcher.go
generated
vendored
@ -23,14 +23,17 @@ import (
|
||||
// RFC7239 has standardized the different forwarding headers into a single header named Forwarded.
|
||||
// The header value has a different format, so you should use forwardedMatcher
|
||||
// when the http01.ProviderServer operates behind a RFC7239 compatible proxy.
|
||||
// https://tools.ietf.org/html/rfc7239
|
||||
// https://www.rfc-editor.org/rfc/rfc7239.html
|
||||
//
|
||||
// Note: RFC7239 also reminds us, "that an HTTP list [...] may be split over multiple header fields" (section 7.1),
|
||||
// meaning that
|
||||
// X-Header: a
|
||||
// X-Header: b
|
||||
//
|
||||
// X-Header: a
|
||||
// X-Header: b
|
||||
//
|
||||
// is equal to
|
||||
// X-Header: a, b
|
||||
//
|
||||
// X-Header: a, b
|
||||
//
|
||||
// All matcher implementations (explicitly not excluding arbitraryMatcher!)
|
||||
// have in common that they only match against the first value in such lists.
|
||||
@ -66,7 +69,7 @@ func (m arbitraryMatcher) matches(r *http.Request, domain string) bool {
|
||||
}
|
||||
|
||||
// forwardedMatcher checks whether the Forwarded header contains a "host" element starting with a domain name.
|
||||
// See https://tools.ietf.org/html/rfc7239 for details.
|
||||
// See https://www.rfc-editor.org/rfc/rfc7239.html for details.
|
||||
type forwardedMatcher struct{}
|
||||
|
||||
func (m *forwardedMatcher) name() string {
|
||||
|
31
vendor/github.com/go-acme/lego/v4/challenge/http01/http_challenge_server.go
generated
vendored
31
vendor/github.com/go-acme/lego/v4/challenge/http01/http_challenge_server.go
generated
vendored
@ -2,9 +2,11 @@ package http01
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
@ -14,8 +16,11 @@ import (
|
||||
// It may be instantiated without using the NewProviderServer function if
|
||||
// you want only to use the default values.
|
||||
type ProviderServer struct {
|
||||
iface string
|
||||
port string
|
||||
address string
|
||||
network string // must be valid argument to net.Listen
|
||||
|
||||
socketMode fs.FileMode
|
||||
|
||||
matcher domainMatcher
|
||||
done chan bool
|
||||
listener net.Listener
|
||||
@ -29,24 +34,34 @@ func NewProviderServer(iface, port string) *ProviderServer {
|
||||
port = "80"
|
||||
}
|
||||
|
||||
return &ProviderServer{iface: iface, port: port, matcher: &hostMatcher{}}
|
||||
return &ProviderServer{network: "tcp", address: net.JoinHostPort(iface, port), matcher: &hostMatcher{}}
|
||||
}
|
||||
|
||||
func NewUnixProviderServer(socketPath string, mode fs.FileMode) *ProviderServer {
|
||||
return &ProviderServer{network: "unix", address: socketPath, socketMode: mode, matcher: &hostMatcher{}}
|
||||
}
|
||||
|
||||
// Present starts a web server and makes the token available at `ChallengePath(token)` for web requests.
|
||||
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
||||
var err error
|
||||
s.listener, err = net.Listen("tcp", s.GetAddress())
|
||||
s.listener, err = net.Listen(s.network, s.GetAddress())
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not start HTTP server for challenge: %w", err)
|
||||
}
|
||||
|
||||
if s.network == "unix" {
|
||||
if err = os.Chmod(s.address, s.socketMode); err != nil {
|
||||
return fmt.Errorf("chmod %s: %w", s.address, err)
|
||||
}
|
||||
}
|
||||
|
||||
s.done = make(chan bool)
|
||||
go s.serve(domain, token, keyAuth)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ProviderServer) GetAddress() string {
|
||||
return net.JoinHostPort(s.iface, s.port)
|
||||
return s.address
|
||||
}
|
||||
|
||||
// CleanUp closes the HTTP server and removes the token from `ChallengePath(token)`.
|
||||
@ -69,7 +84,7 @@ func (s *ProviderServer) CleanUp(domain, token, keyAuth string) error {
|
||||
//
|
||||
// The exact behavior depends on the value of headerName:
|
||||
// - "" (the empty string) and "Host" will restore the default and only check the Host header
|
||||
// - "Forwarded" will look for a Forwarded header, and inspect it according to https://tools.ietf.org/html/rfc7239
|
||||
// - "Forwarded" will look for a Forwarded header, and inspect it according to https://www.rfc-editor.org/rfc/rfc7239.html
|
||||
// - any other value will check the header value with the same name.
|
||||
func (s *ProviderServer) SetProxyHeader(headerName string) {
|
||||
switch h := textproto.CanonicalMIMEHeaderKey(headerName); h {
|
||||
@ -85,7 +100,7 @@ func (s *ProviderServer) SetProxyHeader(headerName string) {
|
||||
func (s *ProviderServer) serve(domain, token, keyAuth string) {
|
||||
path := ChallengePath(token)
|
||||
|
||||
// The incoming request must will be validated to prevent DNS rebind attacks.
|
||||
// The incoming request will be validated to prevent DNS rebind attacks.
|
||||
// We only respond with the keyAuth, when we're receiving a GET requests with
|
||||
// the "Host" header matching the domain (the latter is configurable though SetProxyHeader).
|
||||
mux := http.NewServeMux()
|
||||
@ -99,7 +114,7 @@ func (s *ProviderServer) serve(domain, token, keyAuth string) {
|
||||
}
|
||||
log.Infof("[%s] Served key authentication", domain)
|
||||
} else {
|
||||
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the %s header properly.", r.Host, r.Method, s.matcher.name())
|
||||
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure you are passing the %s header properly.", r.Host, r.Method, s.matcher.name())
|
||||
_, err := w.Write([]byte("TEST"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
2
vendor/github.com/go-acme/lego/v4/challenge/resolver/errors.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/challenge/resolver/errors.go
generated
vendored
@ -19,7 +19,7 @@ func (e obtainError) Error() string {
|
||||
sort.Strings(domains)
|
||||
|
||||
for _, domain := range domains {
|
||||
buffer.WriteString(fmt.Sprintf("[%s] %s\n", domain, e[domain]))
|
||||
_, _ = fmt.Fprintf(buffer, "[%s] %s\n", domain, e[domain])
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
2
vendor/github.com/go-acme/lego/v4/challenge/resolver/prober.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/challenge/resolver/prober.go
generated
vendored
@ -128,7 +128,7 @@ func sequentialSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
|
||||
}
|
||||
|
||||
func parallelSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
|
||||
// For all valid preSolvers, first submit the challenges so they have max time to propagate
|
||||
// For all valid preSolvers, first submit the challenges, so they have max time to propagate
|
||||
for _, authSolver := range authSolvers {
|
||||
authz := authSolver.authz
|
||||
if solvr, ok := authSolver.solver.(preSolver); ok {
|
||||
|
13
vendor/github.com/go-acme/lego/v4/challenge/resolver/solver_manager.go
generated
vendored
13
vendor/github.com/go-acme/lego/v4/challenge/resolver/solver_manager.go
generated
vendored
@ -1,7 +1,6 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
@ -54,7 +53,7 @@ func (c *SolverManager) SetDNS01Provider(p challenge.Provider, opts ...dns01.Cha
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove Remove a challenge type from the available solvers.
|
||||
// Remove removes a challenge type from the available solvers.
|
||||
func (c *SolverManager) Remove(chlgType challenge.Type) {
|
||||
delete(c.solvers, chlgType)
|
||||
}
|
||||
@ -107,21 +106,17 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
|
||||
bo.MaxInterval = 10 * initialInterval
|
||||
bo.MaxElapsedTime = 100 * initialInterval
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// After the path is sent, the ACME server will access our server.
|
||||
// Repeatedly check the server for an updated status on our request.
|
||||
operation := func() error {
|
||||
authz, err := core.Authorizations.Get(chlng.AuthorizationURL)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return err
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
|
||||
valid, err := checkAuthorizationStatus(authz)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return err
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
|
||||
if valid {
|
||||
@ -132,7 +127,7 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
|
||||
return errors.New("the server didn't respond to our request")
|
||||
}
|
||||
|
||||
return backoff.Retry(operation, backoff.WithContext(bo, ctx))
|
||||
return backoff.Retry(operation, bo)
|
||||
}
|
||||
|
||||
func checkChallengeStatus(chlng acme.ExtendedChallenge) (bool, error) {
|
||||
|
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge.go
generated
vendored
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge.go
generated
vendored
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
|
||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-6.1
|
||||
// Reference: https://www.rfc-editor.org/rfc/rfc8737.html#section-6.1
|
||||
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
|
||||
|
||||
type ValidateFunc func(core *api.Core, domain string, chlng acme.Challenge) error
|
||||
@ -83,7 +83,7 @@ func ChallengeBlocks(domain, keyAuth string) ([]byte, []byte, error) {
|
||||
|
||||
// Add the keyAuth digest as the acmeValidation-v1 extension
|
||||
// (marked as critical such that it won't be used by non-ACME software).
|
||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-3
|
||||
// Reference: https://www.rfc-editor.org/rfc/rfc8737.html#section-3
|
||||
extensions := []pkix.Extension{
|
||||
{
|
||||
Id: idPeAcmeIdentifierV1,
|
||||
|
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge_server.go
generated
vendored
4
vendor/github.com/go-acme/lego/v4/challenge/tlsalpn01/tls_alpn_challenge_server.go
generated
vendored
@ -40,7 +40,7 @@ func (s *ProviderServer) GetAddress() string {
|
||||
return net.JoinHostPort(s.iface, s.port)
|
||||
}
|
||||
|
||||
// Present generates a certificate with a SHA-256 digest of the keyAuth provided
|
||||
// Present generates a certificate with an SHA-256 digest of the keyAuth provided
|
||||
// as the acmeValidation-v1 extension value to conform to the ACME-TLS-ALPN spec.
|
||||
func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
||||
if s.port == "" {
|
||||
@ -61,7 +61,7 @@ func (s *ProviderServer) Present(domain, token, keyAuth string) error {
|
||||
|
||||
// We must set that the `acme-tls/1` application level protocol is supported
|
||||
// so that the protocol negotiation can succeed. Reference:
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07#section-6.2
|
||||
// https://www.rfc-editor.org/rfc/rfc8737.html#section-6.2
|
||||
tlsConf.NextProtos = []string{ACMETLS1Protocol}
|
||||
|
||||
// Create the listener with the created tls.Config.
|
||||
|
55
vendor/github.com/go-acme/lego/v4/lego/client_config.go
generated
vendored
55
vendor/github.com/go-acme/lego/v4/lego/client_config.go
generated
vendored
@ -4,10 +4,11 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
@ -17,13 +18,18 @@ import (
|
||||
const (
|
||||
// caCertificatesEnvVar is the environment variable name that can be used to
|
||||
// specify the path to PEM encoded CA Certificates that can be used to
|
||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
||||
// authenticate an ACME server with an HTTPS certificate not issued by a CA in
|
||||
// the system-wide trusted root list.
|
||||
// Multiple file paths can be added by using os.PathListSeparator as a separator.
|
||||
caCertificatesEnvVar = "LEGO_CA_CERTIFICATES"
|
||||
|
||||
// caSystemCertPool is the environment variable name that can be used to define
|
||||
// if the certificates pool must use a copy of the system cert pool.
|
||||
caSystemCertPool = "LEGO_CA_SYSTEM_CERT_POOL"
|
||||
|
||||
// caServerNameEnvVar is the environment variable name that can be used to
|
||||
// specify the CA server name that can be used to
|
||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
||||
// authenticate an ACME server with an HTTPS certificate not issued by a CA in
|
||||
// the system-wide trusted root list.
|
||||
caServerNameEnvVar = "LEGO_CA_SERVER_NAME"
|
||||
|
||||
@ -82,23 +88,44 @@ func createDefaultHTTPClient() *http.Client {
|
||||
}
|
||||
|
||||
// initCertPool creates a *x509.CertPool populated with the PEM certificates
|
||||
// found in the filepath specified in the caCertificatesEnvVar OS environment
|
||||
// variable. If the caCertificatesEnvVar is not set then initCertPool will
|
||||
// return nil. If there is an error creating a *x509.CertPool from the provided
|
||||
// caCertificatesEnvVar value then initCertPool will panic.
|
||||
// found in the filepath specified in the caCertificatesEnvVar OS environment variable.
|
||||
// If the caCertificatesEnvVar is not set then initCertPool will return nil.
|
||||
// If there is an error creating a *x509.CertPool from the provided caCertificatesEnvVar value then initCertPool will panic.
|
||||
// If the caSystemCertPool is set to a "truthy value" (`1`, `t`, `T`, `TRUE`, `true`, `True`) then a copy of system cert pool will be used.
|
||||
// caSystemCertPool requires caCertificatesEnvVar to be set.
|
||||
func initCertPool() *x509.CertPool {
|
||||
if customCACertsPath := os.Getenv(caCertificatesEnvVar); customCACertsPath != "" {
|
||||
customCAs, err := ioutil.ReadFile(customCACertsPath)
|
||||
customCACertsPath := os.Getenv(caCertificatesEnvVar)
|
||||
if customCACertsPath == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
certPool := getCertPool()
|
||||
|
||||
for _, customPath := range strings.Split(customCACertsPath, string(os.PathListSeparator)) {
|
||||
customCAs, err := os.ReadFile(customPath)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error reading %s=%q: %v",
|
||||
caCertificatesEnvVar, customCACertsPath, err))
|
||||
caCertificatesEnvVar, customPath, err))
|
||||
}
|
||||
certPool := x509.NewCertPool()
|
||||
|
||||
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
||||
panic(fmt.Sprintf("error creating x509 cert pool from %s=%q: %v",
|
||||
caCertificatesEnvVar, customCACertsPath, err))
|
||||
caCertificatesEnvVar, customPath, err))
|
||||
}
|
||||
return certPool
|
||||
}
|
||||
return nil
|
||||
|
||||
return certPool
|
||||
}
|
||||
|
||||
func getCertPool() *x509.CertPool {
|
||||
useSystemCertPool, _ := strconv.ParseBool(os.Getenv(caSystemCertPool))
|
||||
if !useSystemCertPool {
|
||||
return x509.NewCertPool()
|
||||
}
|
||||
|
||||
pool, err := x509.SystemCertPool()
|
||||
if err == nil {
|
||||
return pool
|
||||
}
|
||||
return x509.NewCertPool()
|
||||
}
|
||||
|
2
vendor/github.com/go-acme/lego/v4/log/logger.go
generated
vendored
2
vendor/github.com/go-acme/lego/v4/log/logger.go
generated
vendored
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// Logger is an optional custom logger.
|
||||
var Logger StdLogger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
var Logger StdLogger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
|
||||
// StdLogger interface for Standard Logger.
|
||||
type StdLogger interface {
|
||||
|
95
vendor/github.com/go-acme/lego/v4/platform/config/env/env.go
generated
vendored
95
vendor/github.com/go-acme/lego/v4/platform/config/env/env.go
generated
vendored
@ -3,7 +3,6 @@ package env
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -55,7 +54,6 @@ func Get(names ...string) (map[string]string, error) {
|
||||
// // LEGO_TWO=""
|
||||
// env.GetWithFallback([]string{"LEGO_ONE", "LEGO_TWO"})
|
||||
// // => error
|
||||
//
|
||||
func GetWithFallback(groups ...[]string) (map[string]string, error) {
|
||||
values := map[string]string{}
|
||||
|
||||
@ -80,15 +78,26 @@ func GetWithFallback(groups ...[]string) (map[string]string, error) {
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func GetOneWithFallback[T any](main string, defaultValue T, fn func(string) (T, error), names ...string) T {
|
||||
v, _ := getOneWithFallback(main, names...)
|
||||
|
||||
value, err := fn(v)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func getOneWithFallback(main string, names ...string) (string, string) {
|
||||
value := GetOrFile(main)
|
||||
if len(value) > 0 {
|
||||
if value != "" {
|
||||
return value, main
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
value := GetOrFile(name)
|
||||
if len(value) > 0 {
|
||||
if value != "" {
|
||||
return value, main
|
||||
}
|
||||
}
|
||||
@ -96,43 +105,32 @@ func getOneWithFallback(main string, names ...string) (string, string) {
|
||||
return "", main
|
||||
}
|
||||
|
||||
// GetOrDefaultInt returns the given environment variable value as an integer.
|
||||
// Returns the default if the envvar cannot be coopered to an int, or is not found.
|
||||
func GetOrDefaultInt(envVar string, defaultValue int) int {
|
||||
v, err := strconv.Atoi(GetOrFile(envVar))
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// GetOrDefaultSecond returns the given environment variable value as an time.Duration (second).
|
||||
// Returns the default if the envvar cannot be coopered to an int, or is not found.
|
||||
func GetOrDefaultSecond(envVar string, defaultValue time.Duration) time.Duration {
|
||||
v := GetOrDefaultInt(envVar, -1)
|
||||
if v < 0 {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return time.Duration(v) * time.Second
|
||||
}
|
||||
|
||||
// GetOrDefaultString returns the given environment variable value as a string.
|
||||
// Returns the default if the envvar cannot be find.
|
||||
func GetOrDefaultString(envVar, defaultValue string) string {
|
||||
v := GetOrFile(envVar)
|
||||
if v == "" {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return v
|
||||
// Returns the default if the env var cannot be found.
|
||||
func GetOrDefaultString(envVar string, defaultValue string) string {
|
||||
return getOrDefault(envVar, defaultValue, ParseString)
|
||||
}
|
||||
|
||||
// GetOrDefaultBool returns the given environment variable value as a boolean.
|
||||
// Returns the default if the envvar cannot be coopered to a boolean, or is not found.
|
||||
// Returns the default if the env var cannot be coopered to a boolean, or is not found.
|
||||
func GetOrDefaultBool(envVar string, defaultValue bool) bool {
|
||||
v, err := strconv.ParseBool(GetOrFile(envVar))
|
||||
return getOrDefault(envVar, defaultValue, strconv.ParseBool)
|
||||
}
|
||||
|
||||
// GetOrDefaultInt returns the given environment variable value as an integer.
|
||||
// Returns the default if the env var cannot be coopered to an int, or is not found.
|
||||
func GetOrDefaultInt(envVar string, defaultValue int) int {
|
||||
return getOrDefault(envVar, defaultValue, strconv.Atoi)
|
||||
}
|
||||
|
||||
// GetOrDefaultSecond returns the given environment variable value as a time.Duration (second).
|
||||
// Returns the default if the env var cannot be coopered to an int, or is not found.
|
||||
func GetOrDefaultSecond(envVar string, defaultValue time.Duration) time.Duration {
|
||||
return getOrDefault(envVar, defaultValue, ParseSecond)
|
||||
}
|
||||
|
||||
func getOrDefault[T any](envVar string, defaultValue T, fn func(string) (T, error)) T {
|
||||
v, err := fn(GetOrFile(envVar))
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
@ -155,7 +153,7 @@ func GetOrFile(envVar string) string {
|
||||
return envVarValue
|
||||
}
|
||||
|
||||
fileContents, err := ioutil.ReadFile(fileVarValue)
|
||||
fileContents, err := os.ReadFile(fileVarValue)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read the file %s (defined by env var %s): %s", fileVarValue, fileVar, err)
|
||||
return ""
|
||||
@ -163,3 +161,26 @@ func GetOrFile(envVar string) string {
|
||||
|
||||
return strings.TrimSuffix(string(fileContents), "\n")
|
||||
}
|
||||
|
||||
// ParseSecond parses env var value (string) to a second (time.Duration).
|
||||
func ParseSecond(s string) (time.Duration, error) {
|
||||
v, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if v < 0 {
|
||||
return 0, fmt.Errorf("unsupported value: %d", v)
|
||||
}
|
||||
|
||||
return time.Duration(v) * time.Second, nil
|
||||
}
|
||||
|
||||
// ParseString parses env var value (string) to a string but throws an error when the string is empty.
|
||||
func ParseString(s string) (string, error) {
|
||||
if s == "" {
|
||||
return "", errors.New("empty string")
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
5
vendor/github.com/go-acme/lego/v4/platform/wait/wait.go
generated
vendored
5
vendor/github.com/go-acme/lego/v4/platform/wait/wait.go
generated
vendored
@ -16,7 +16,10 @@ func For(msg string, timeout, interval time.Duration, f func() (bool, error)) er
|
||||
for {
|
||||
select {
|
||||
case <-timeUp:
|
||||
return fmt.Errorf("time limit exceeded: last error: %w", lastErr)
|
||||
if lastErr == nil {
|
||||
return fmt.Errorf("%s: time limit exceeded", msg)
|
||||
}
|
||||
return fmt.Errorf("%s: time limit exceeded: last error: %w", msg, lastErr)
|
||||
default:
|
||||
}
|
||||
|
||||
|
133
vendor/github.com/go-acme/lego/v4/providers/dns/internal/errutils/client.go
generated
vendored
Normal file
133
vendor/github.com/go-acme/lego/v4/providers/dns/internal/errutils/client.go
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
package errutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const legoDebugClientVerboseError = "LEGO_DEBUG_CLIENT_VERBOSE_ERROR"
|
||||
|
||||
// HTTPDoError uses with `(http.Client).Do` error.
|
||||
type HTTPDoError struct {
|
||||
req *http.Request
|
||||
err error
|
||||
}
|
||||
|
||||
// NewHTTPDoError creates a new HTTPDoError.
|
||||
func NewHTTPDoError(req *http.Request, err error) *HTTPDoError {
|
||||
return &HTTPDoError{req: req, err: err}
|
||||
}
|
||||
|
||||
func (h HTTPDoError) Error() string {
|
||||
msg := "unable to communicate with the API server:"
|
||||
|
||||
if ok, _ := strconv.ParseBool(os.Getenv(legoDebugClientVerboseError)); ok {
|
||||
msg += fmt.Sprintf(" [request: %s %s]", h.req.Method, h.req.URL)
|
||||
}
|
||||
|
||||
if h.err == nil {
|
||||
return msg
|
||||
}
|
||||
|
||||
return msg + fmt.Sprintf(" error: %v", h.err)
|
||||
}
|
||||
|
||||
func (h HTTPDoError) Unwrap() error {
|
||||
return h.err
|
||||
}
|
||||
|
||||
// ReadResponseError use with `io.ReadAll` when reading response body.
|
||||
type ReadResponseError struct {
|
||||
req *http.Request
|
||||
StatusCode int
|
||||
err error
|
||||
}
|
||||
|
||||
// NewReadResponseError creates a new ReadResponseError.
|
||||
func NewReadResponseError(req *http.Request, statusCode int, err error) *ReadResponseError {
|
||||
return &ReadResponseError{req: req, StatusCode: statusCode, err: err}
|
||||
}
|
||||
|
||||
func (r ReadResponseError) Error() string {
|
||||
msg := "unable to read response body:"
|
||||
|
||||
if ok, _ := strconv.ParseBool(os.Getenv(legoDebugClientVerboseError)); ok {
|
||||
msg += fmt.Sprintf(" [request: %s %s]", r.req.Method, r.req.URL)
|
||||
}
|
||||
|
||||
msg += fmt.Sprintf(" [status code: %d]", r.StatusCode)
|
||||
|
||||
if r.err == nil {
|
||||
return msg
|
||||
}
|
||||
|
||||
return msg + fmt.Sprintf(" error: %v", r.err)
|
||||
}
|
||||
|
||||
func (r ReadResponseError) Unwrap() error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
// UnmarshalError uses with `json.Unmarshal` or `xml.Unmarshal` when reading response body.
|
||||
type UnmarshalError struct {
|
||||
req *http.Request
|
||||
StatusCode int
|
||||
Body []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// NewUnmarshalError creates a new UnmarshalError.
|
||||
func NewUnmarshalError(req *http.Request, statusCode int, body []byte, err error) *UnmarshalError {
|
||||
return &UnmarshalError{req: req, StatusCode: statusCode, Body: bytes.TrimSpace(body), err: err}
|
||||
}
|
||||
|
||||
func (u UnmarshalError) Error() string {
|
||||
msg := "unable to unmarshal response:"
|
||||
|
||||
if ok, _ := strconv.ParseBool(os.Getenv(legoDebugClientVerboseError)); ok {
|
||||
msg += fmt.Sprintf(" [request: %s %s]", u.req.Method, u.req.URL)
|
||||
}
|
||||
|
||||
msg += fmt.Sprintf(" [status code: %d] body: %s", u.StatusCode, string(u.Body))
|
||||
|
||||
if u.err == nil {
|
||||
return msg
|
||||
}
|
||||
|
||||
return msg + fmt.Sprintf(" error: %v", u.err)
|
||||
}
|
||||
|
||||
func (u UnmarshalError) Unwrap() error {
|
||||
return u.err
|
||||
}
|
||||
|
||||
// UnexpectedStatusCodeError use when the status of the response is unexpected but there is no API error type.
|
||||
type UnexpectedStatusCodeError struct {
|
||||
req *http.Request
|
||||
StatusCode int
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// NewUnexpectedStatusCodeError creates a new UnexpectedStatusCodeError.
|
||||
func NewUnexpectedStatusCodeError(req *http.Request, statusCode int, body []byte) *UnexpectedStatusCodeError {
|
||||
return &UnexpectedStatusCodeError{req: req, StatusCode: statusCode, Body: bytes.TrimSpace(body)}
|
||||
}
|
||||
|
||||
func NewUnexpectedResponseStatusCodeError(req *http.Request, resp *http.Response) *UnexpectedStatusCodeError {
|
||||
raw, _ := io.ReadAll(resp.Body)
|
||||
return &UnexpectedStatusCodeError{req: req, StatusCode: resp.StatusCode, Body: bytes.TrimSpace(raw)}
|
||||
}
|
||||
|
||||
func (u UnexpectedStatusCodeError) Error() string {
|
||||
msg := "unexpected status code:"
|
||||
|
||||
if ok, _ := strconv.ParseBool(os.Getenv(legoDebugClientVerboseError)); ok {
|
||||
msg += fmt.Sprintf(" [request: %s %s]", u.req.Method, u.req.URL)
|
||||
}
|
||||
|
||||
return msg + fmt.Sprintf(" [status code: %d] body: %s", u.StatusCode, string(u.Body))
|
||||
}
|
179
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.go
generated
vendored
179
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.go
generated
vendored
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -15,16 +14,14 @@ import (
|
||||
)
|
||||
|
||||
// OVH API reference: https://eu.api.ovh.com/
|
||||
// Create a Token: https://eu.api.ovh.com/createToken/
|
||||
// Create a Token: https://eu.api.ovh.com/createToken/
|
||||
// Create a OAuth2 client: https://eu.api.ovh.com/console-preview/?section=%2Fme&branch=v1#post-/me/api/oauth2/client
|
||||
|
||||
// Environment variables names.
|
||||
const (
|
||||
envNamespace = "OVH_"
|
||||
|
||||
EnvEndpoint = envNamespace + "ENDPOINT"
|
||||
EnvApplicationKey = envNamespace + "APPLICATION_KEY"
|
||||
EnvApplicationSecret = envNamespace + "APPLICATION_SECRET"
|
||||
EnvConsumerKey = envNamespace + "CONSUMER_KEY"
|
||||
EnvEndpoint = envNamespace + "ENDPOINT"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
@ -32,6 +29,19 @@ const (
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
)
|
||||
|
||||
// Authenticate using application key.
|
||||
const (
|
||||
EnvApplicationKey = envNamespace + "APPLICATION_KEY"
|
||||
EnvApplicationSecret = envNamespace + "APPLICATION_SECRET"
|
||||
EnvConsumerKey = envNamespace + "CONSUMER_KEY"
|
||||
)
|
||||
|
||||
// Authenticate using OAuth2 client.
|
||||
const (
|
||||
EnvClientID = envNamespace + "CLIENT_ID"
|
||||
EnvClientSecret = envNamespace + "CLIENT_SECRET"
|
||||
)
|
||||
|
||||
// Record a DNS record.
|
||||
type Record struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
@ -42,18 +52,32 @@ type Record struct {
|
||||
Zone string `json:"zone,omitempty"`
|
||||
}
|
||||
|
||||
// OAuth2Config the OAuth2 specific configuration.
|
||||
type OAuth2Config struct {
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
APIEndpoint string
|
||||
ApplicationKey string
|
||||
ApplicationSecret string
|
||||
ConsumerKey string
|
||||
APIEndpoint string
|
||||
|
||||
ApplicationKey string
|
||||
ApplicationSecret string
|
||||
ConsumerKey string
|
||||
|
||||
OAuth2Config *OAuth2Config
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
func (c *Config) hasAppKeyAuth() bool {
|
||||
return c.ApplicationKey != "" || c.ApplicationSecret != "" || c.ConsumerKey != ""
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
@ -78,17 +102,11 @@ type DNSProvider struct {
|
||||
// Credentials must be passed in the environment variables:
|
||||
// OVH_ENDPOINT (must be either "ovh-eu" or "ovh-ca"), OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvEndpoint, EnvApplicationKey, EnvApplicationSecret, EnvConsumerKey)
|
||||
config, err := createConfigFromEnvVars()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ovh: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.APIEndpoint = values[EnvEndpoint]
|
||||
config.ApplicationKey = values[EnvApplicationKey]
|
||||
config.ApplicationSecret = values[EnvApplicationSecret]
|
||||
config.ConsumerKey = values[EnvConsumerKey]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
@ -98,16 +116,11 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
return nil, errors.New("ovh: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.APIEndpoint == "" || config.ApplicationKey == "" || config.ApplicationSecret == "" || config.ConsumerKey == "" {
|
||||
return nil, errors.New("ovh: credentials missing")
|
||||
if config.OAuth2Config != nil && config.hasAppKeyAuth() {
|
||||
return nil, errors.New("ovh: can't use both authentication systems (ApplicationKey and OAuth2)")
|
||||
}
|
||||
|
||||
client, err := ovh.NewClient(
|
||||
config.APIEndpoint,
|
||||
config.ApplicationKey,
|
||||
config.ApplicationSecret,
|
||||
config.ConsumerKey,
|
||||
)
|
||||
client, err := newClient(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ovh: %w", err)
|
||||
}
|
||||
@ -123,19 +136,23 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
|
||||
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
// Parse domain name
|
||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", domain, err)
|
||||
return fmt.Errorf("ovh: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
authZone = dns01.UnFqdn(authZone)
|
||||
subDomain := extractRecordName(fqdn, authZone)
|
||||
|
||||
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ovh: %w", err)
|
||||
}
|
||||
|
||||
reqURL := fmt.Sprintf("/domain/zone/%s/record", authZone)
|
||||
reqData := Record{FieldType: "TXT", SubDomain: subDomain, Target: value, TTL: d.config.TTL}
|
||||
reqData := Record{FieldType: "TXT", SubDomain: subDomain, Target: info.Value, TTL: d.config.TTL}
|
||||
|
||||
// Create TXT record
|
||||
var respData Record
|
||||
@ -160,19 +177,19 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
// get the record's unique ID from when we created it
|
||||
d.recordIDsMu.Lock()
|
||||
recordID, ok := d.recordIDs[token]
|
||||
d.recordIDsMu.Unlock()
|
||||
if !ok {
|
||||
return fmt.Errorf("ovh: unknown record ID for '%s'", fqdn)
|
||||
return fmt.Errorf("ovh: unknown record ID for '%s'", info.EffectiveFQDN)
|
||||
}
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ovh: could not determine zone for domain %q: %w", domain, err)
|
||||
return fmt.Errorf("ovh: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
authZone = dns01.UnFqdn(authZone)
|
||||
@ -205,10 +222,94 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func extractRecordName(fqdn, zone string) string {
|
||||
name := dns01.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+zone); idx != -1 {
|
||||
return name[:idx]
|
||||
func createConfigFromEnvVars() (*Config, error) {
|
||||
firstAppKeyEnvVar := findFirstValuedEnvVar(EnvApplicationKey, EnvApplicationSecret, EnvConsumerKey)
|
||||
firstOAuth2EnvVar := findFirstValuedEnvVar(EnvClientID, EnvClientSecret)
|
||||
|
||||
if firstAppKeyEnvVar != "" && firstOAuth2EnvVar != "" {
|
||||
return nil, fmt.Errorf("can't use both %s and %s at the same time", firstAppKeyEnvVar, firstOAuth2EnvVar)
|
||||
}
|
||||
return name
|
||||
|
||||
config := NewDefaultConfig()
|
||||
|
||||
if firstOAuth2EnvVar != "" {
|
||||
values, err := env.Get(EnvEndpoint, EnvClientID, EnvClientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.APIEndpoint = values[EnvEndpoint]
|
||||
config.OAuth2Config = &OAuth2Config{
|
||||
ClientID: values[EnvClientID],
|
||||
ClientSecret: values[EnvClientSecret],
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
values, err := env.Get(EnvEndpoint, EnvApplicationKey, EnvApplicationSecret, EnvConsumerKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.APIEndpoint = values[EnvEndpoint]
|
||||
|
||||
config.ApplicationKey = values[EnvApplicationKey]
|
||||
config.ApplicationSecret = values[EnvApplicationSecret]
|
||||
config.ConsumerKey = values[EnvConsumerKey]
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func findFirstValuedEnvVar(envVars ...string) string {
|
||||
for _, envVar := range envVars {
|
||||
if env.GetOrFile(envVar) != "" {
|
||||
return envVar
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func newClient(config *Config) (*ovh.Client, error) {
|
||||
if config.OAuth2Config == nil {
|
||||
return newClientApplicationKey(config)
|
||||
}
|
||||
|
||||
return newClientOAuth2(config)
|
||||
}
|
||||
|
||||
func newClientApplicationKey(config *Config) (*ovh.Client, error) {
|
||||
if config.APIEndpoint == "" || config.ApplicationKey == "" || config.ApplicationSecret == "" || config.ConsumerKey == "" {
|
||||
return nil, errors.New("credentials are missing")
|
||||
}
|
||||
|
||||
client, err := ovh.NewClient(
|
||||
config.APIEndpoint,
|
||||
config.ApplicationKey,
|
||||
config.ApplicationSecret,
|
||||
config.ConsumerKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new client: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func newClientOAuth2(config *Config) (*ovh.Client, error) {
|
||||
if config.APIEndpoint == "" || config.OAuth2Config.ClientID == "" || config.OAuth2Config.ClientSecret == "" {
|
||||
return nil, errors.New("credentials are missing")
|
||||
}
|
||||
|
||||
client, err := ovh.NewOAuth2Client(
|
||||
config.APIEndpoint,
|
||||
config.OAuth2Config.ClientID,
|
||||
config.OAuth2Config.ClientSecret,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new OAuth2 client: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
37
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.toml
generated
vendored
37
vendor/github.com/go-acme/lego/v4/providers/dns/ovh/ovh.toml
generated
vendored
@ -5,11 +5,20 @@ Code = "ovh"
|
||||
Since = "v0.4.0"
|
||||
|
||||
Example = '''
|
||||
# Application Key authentication:
|
||||
|
||||
OVH_APPLICATION_KEY=1234567898765432 \
|
||||
OVH_APPLICATION_SECRET=b9841238feb177a84330febba8a832089 \
|
||||
OVH_CONSUMER_KEY=256vfsd347245sdfg \
|
||||
OVH_ENDPOINT=ovh-eu \
|
||||
lego --email myemail@example.com --dns autodns --domains my.example.org run
|
||||
lego --email you@example.com --dns ovh --domains my.example.org run
|
||||
|
||||
# Or OAuth2:
|
||||
|
||||
OVH_CLIENT_ID=yyy \
|
||||
OVH_CLIENT_SECRET=xxx \
|
||||
OVH_ENDPOINT=ovh-eu \
|
||||
lego --email you@example.com --dns ovh --domains my.example.org run
|
||||
'''
|
||||
|
||||
Additional = '''
|
||||
@ -17,7 +26,7 @@ Additional = '''
|
||||
|
||||
Application key and secret can be created by following the [OVH guide](https://docs.ovh.com/gb/en/customer/first-steps-with-ovh-api/).
|
||||
|
||||
When requesting the consumer key, the following configuration can be use to define access rights:
|
||||
When requesting the consumer key, the following configuration can be used to define access rights:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -33,14 +42,32 @@ When requesting the consumer key, the following configuration can be use to defi
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## OAuth2 Client Credentials
|
||||
|
||||
Another method for authentication is by using OAuth2 client credentials.
|
||||
|
||||
An IAM policy and service account can be created by following the [OVH guide](https://help.ovhcloud.com/csm/en-manage-service-account?id=kb_article_view&sysparm_article=KB0059343).
|
||||
|
||||
Following IAM policies need to be authorized for the affected domain:
|
||||
|
||||
* dnsZone:apiovh:record/create
|
||||
* dnsZone:apiovh:record/delete
|
||||
* dnsZone:apiovh:refresh
|
||||
|
||||
## Important Note
|
||||
|
||||
Both authentication methods cannot be used at the same time.
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
OVH_ENDPOINT = "Endpoint URL (ovh-eu or ovh-ca)"
|
||||
OVH_APPLICATION_KEY = "Application key"
|
||||
OVH_APPLICATION_SECRET = "Application secret"
|
||||
OVH_CONSUMER_KEY = "Consumer key"
|
||||
OVH_APPLICATION_KEY = "Application key (Application Key authentication)"
|
||||
OVH_APPLICATION_SECRET = "Application secret (Application Key authentication)"
|
||||
OVH_CONSUMER_KEY = "Consumer key (Application Key authentication)"
|
||||
OVH_CLIENT_ID = "Client ID (OAuth2)"
|
||||
OVH_CLIENT_SECRET = "Client secret (OAuth2)"
|
||||
[Configuration.Additional]
|
||||
OVH_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
OVH_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
|
228
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/internal/client.go
generated
vendored
Normal file
228
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/internal/client.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Client the PowerDNS API client.
|
||||
type Client struct {
|
||||
serverName string
|
||||
apiKey string
|
||||
|
||||
apiVersion int
|
||||
|
||||
Host *url.URL
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient creates a new Client.
|
||||
func NewClient(host *url.URL, serverName string, apiVersion int, apiKey string) *Client {
|
||||
return &Client{
|
||||
serverName: serverName,
|
||||
apiKey: apiKey,
|
||||
apiVersion: apiVersion,
|
||||
Host: host,
|
||||
HTTPClient: &http.Client{Timeout: 5 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) APIVersion() int {
|
||||
return c.apiVersion
|
||||
}
|
||||
|
||||
func (c *Client) SetAPIVersion(ctx context.Context) error {
|
||||
var err error
|
||||
|
||||
c.apiVersion, err = c.getAPIVersion(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) getAPIVersion(ctx context.Context) (int, error) {
|
||||
endpoint := c.joinPath("/", "api")
|
||||
|
||||
req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
result, err := c.do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var versions []apiVersion
|
||||
err = json.Unmarshal(result, &versions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
latestVersion := 0
|
||||
for _, v := range versions {
|
||||
if v.Version > latestVersion {
|
||||
latestVersion = v.Version
|
||||
}
|
||||
}
|
||||
|
||||
return latestVersion, err
|
||||
}
|
||||
|
||||
func (c *Client) GetHostedZone(ctx context.Context, authZone string) (*HostedZone, error) {
|
||||
endpoint := c.joinPath("/", "servers", c.serverName, "zones", dns.Fqdn(authZone))
|
||||
|
||||
req, err := newJSONRequest(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := c.do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var zone HostedZone
|
||||
err = json.Unmarshal(result, &zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// convert pre-v1 API result
|
||||
if len(zone.Records) > 0 {
|
||||
zone.RRSets = []RRSet{}
|
||||
for _, record := range zone.Records {
|
||||
set := RRSet{
|
||||
Name: record.Name,
|
||||
Type: record.Type,
|
||||
Records: []Record{record},
|
||||
}
|
||||
zone.RRSets = append(zone.RRSets, set)
|
||||
}
|
||||
}
|
||||
|
||||
return &zone, nil
|
||||
}
|
||||
|
||||
func (c *Client) UpdateRecords(ctx context.Context, zone *HostedZone, sets RRSets) error {
|
||||
endpoint := c.joinPath("/", "servers", c.serverName, "zones", zone.ID)
|
||||
|
||||
req, err := newJSONRequest(ctx, http.MethodPatch, endpoint, sets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Notify(ctx context.Context, zone *HostedZone) error {
|
||||
if c.apiVersion < 1 || zone.Kind != "Master" && zone.Kind != "Slave" {
|
||||
return nil
|
||||
}
|
||||
|
||||
endpoint := c.joinPath("/", "servers", c.serverName, "zones", zone.ID, "notify")
|
||||
|
||||
req, err := newJSONRequest(ctx, http.MethodPut, endpoint, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) joinPath(elem ...string) *url.URL {
|
||||
p := path.Join(elem...)
|
||||
|
||||
if p != "/api" && c.apiVersion > 0 && !strings.HasPrefix(p, "/api/v") {
|
||||
p = path.Join("/api", "v"+strconv.Itoa(c.apiVersion), p)
|
||||
}
|
||||
|
||||
return c.Host.JoinPath(p)
|
||||
}
|
||||
|
||||
func (c *Client) do(req *http.Request) (json.RawMessage, error) {
|
||||
req.Header.Set("X-API-Key", c.apiKey)
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, errutils.NewHTTPDoError(req, err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusUnprocessableEntity && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
|
||||
return nil, errutils.NewUnexpectedResponseStatusCodeError(req, resp)
|
||||
}
|
||||
|
||||
var msg json.RawMessage
|
||||
err = json.NewDecoder(resp.Body).Decode(&msg)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
// empty body
|
||||
return nil, nil
|
||||
}
|
||||
// other error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for PowerDNS error message
|
||||
if len(msg) > 0 && msg[0] == '{' {
|
||||
var errInfo apiError
|
||||
err = json.Unmarshal(msg, &errInfo)
|
||||
if err != nil {
|
||||
return nil, errutils.NewUnmarshalError(req, resp.StatusCode, msg, err)
|
||||
}
|
||||
if errInfo.ShortMsg != "" {
|
||||
return nil, fmt.Errorf("error talking to PDNS API: %w", errInfo)
|
||||
}
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, payload any) (*http.Request, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if payload != nil {
|
||||
err := json.NewEncoder(buf).Encode(payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request JSON body: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, strings.TrimSuffix(endpoint.String(), "/"), buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
// PowerDNS doesn't follow HTTP convention about the "Content-Type" header.
|
||||
if method != http.MethodGet && method != http.MethodDelete {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
48
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/internal/types.go
generated
vendored
Normal file
48
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/internal/types.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package internal
|
||||
|
||||
type Record struct {
|
||||
Content string `json:"content"`
|
||||
Disabled bool `json:"disabled"`
|
||||
|
||||
// pre-v1 API
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
TTL int `json:"ttl,omitempty"`
|
||||
}
|
||||
|
||||
type HostedZone struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Kind string `json:"kind"`
|
||||
RRSets []RRSet `json:"rrsets"`
|
||||
|
||||
// pre-v1 API
|
||||
Records []Record `json:"records"`
|
||||
}
|
||||
|
||||
type RRSet struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Kind string `json:"kind"`
|
||||
ChangeType string `json:"changetype"`
|
||||
Records []Record `json:"records,omitempty"`
|
||||
TTL int `json:"ttl,omitempty"`
|
||||
}
|
||||
|
||||
type RRSets struct {
|
||||
RRSets []RRSet `json:"rrsets"`
|
||||
}
|
||||
|
||||
type apiError struct {
|
||||
ShortMsg string `json:"error"`
|
||||
}
|
||||
|
||||
func (a apiError) Error() string {
|
||||
return a.ShortMsg
|
||||
}
|
||||
|
||||
type apiVersion struct {
|
||||
URL string `json:"url"`
|
||||
Version int `json:"version"`
|
||||
}
|
228
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/pdns.go
generated
vendored
Normal file
228
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/pdns.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
// Package pdns implements a DNS provider for solving the DNS-01 challenge using PowerDNS nameserver.
|
||||
package pdns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/go-acme/lego/v4/providers/dns/pdns/internal"
|
||||
)
|
||||
|
||||
// Environment variables names.
|
||||
const (
|
||||
envNamespace = "PDNS_"
|
||||
|
||||
EnvAPIKey = envNamespace + "API_KEY"
|
||||
EnvAPIURL = envNamespace + "API_URL"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvAPIVersion = envNamespace + "API_VERSION"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
EnvServerName = envNamespace + "SERVER_NAME"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
APIKey string
|
||||
Host *url.URL
|
||||
ServerName string
|
||||
APIVersion int
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
ServerName: env.GetOrDefaultString(EnvServerName, "localhost"),
|
||||
APIVersion: env.GetOrDefaultInt(EnvAPIVersion, 0),
|
||||
TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 120*time.Second),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, 2*time.Second),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider implements the challenge.Provider interface.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *internal.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for pdns.
|
||||
// Credentials must be passed in the environment variable:
|
||||
// PDNS_API_URL and PDNS_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAPIKey, EnvAPIURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
hostURL, err := url.Parse(values[EnvAPIURL])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.Host = hostURL
|
||||
config.APIKey = values[EnvAPIKey]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider instance configured for pdns.
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("pdns: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.APIKey == "" {
|
||||
return nil, errors.New("pdns: API key missing")
|
||||
}
|
||||
|
||||
if config.Host == nil || config.Host.Host == "" {
|
||||
return nil, errors.New("pdns: API URL missing")
|
||||
}
|
||||
|
||||
client := internal.NewClient(config.Host, config.ServerName, config.APIVersion, config.APIKey)
|
||||
|
||||
if config.APIVersion <= 0 {
|
||||
err := client.SetAPIVersion(context.Background())
|
||||
if err != nil {
|
||||
log.Warnf("pdns: failed to get API version %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &DNSProvider{config: config, client: client}, nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
// Adjusting here to cope with spikes in propagation times.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
zone, err := d.client.GetHostedZone(ctx, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
name := info.EffectiveFQDN
|
||||
if d.client.APIVersion() == 0 {
|
||||
// pre-v1 API wants non-fqdn
|
||||
name = dns01.UnFqdn(info.EffectiveFQDN)
|
||||
}
|
||||
|
||||
// Look for existing records.
|
||||
existingRRSet := findTxtRecord(zone, info.EffectiveFQDN)
|
||||
|
||||
// merge the existing and new records
|
||||
var records []internal.Record
|
||||
if existingRRSet != nil {
|
||||
records = existingRRSet.Records
|
||||
}
|
||||
|
||||
rec := internal.Record{
|
||||
Content: "\"" + info.Value + "\"",
|
||||
Disabled: false,
|
||||
|
||||
// pre-v1 API
|
||||
Type: "TXT",
|
||||
Name: name,
|
||||
TTL: d.config.TTL,
|
||||
}
|
||||
|
||||
rrSets := internal.RRSets{
|
||||
RRSets: []internal.RRSet{
|
||||
{
|
||||
Name: name,
|
||||
ChangeType: "REPLACE",
|
||||
Type: "TXT",
|
||||
Kind: "Master",
|
||||
TTL: d.config.TTL,
|
||||
Records: append(records, rec),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = d.client.UpdateRecords(ctx, zone, rrSets)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
return d.client.Notify(ctx, zone)
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
zone, err := d.client.GetHostedZone(ctx, authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
set := findTxtRecord(zone, info.EffectiveFQDN)
|
||||
|
||||
if set == nil {
|
||||
return fmt.Errorf("pdns: no existing record found for %s", info.EffectiveFQDN)
|
||||
}
|
||||
|
||||
rrSets := internal.RRSets{
|
||||
RRSets: []internal.RRSet{
|
||||
{
|
||||
Name: set.Name,
|
||||
Type: set.Type,
|
||||
ChangeType: "DELETE",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = d.client.UpdateRecords(ctx, zone, rrSets)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pdns: %w", err)
|
||||
}
|
||||
|
||||
return d.client.Notify(ctx, zone)
|
||||
}
|
||||
|
||||
func findTxtRecord(zone *internal.HostedZone, fqdn string) *internal.RRSet {
|
||||
for _, set := range zone.RRSets {
|
||||
if set.Type == "TXT" && (set.Name == dns01.UnFqdn(fqdn) || set.Name == fqdn) {
|
||||
return &set
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
37
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/pdns.toml
generated
vendored
Normal file
37
vendor/github.com/go-acme/lego/v4/providers/dns/pdns/pdns.toml
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
Name = "PowerDNS"
|
||||
Description = ''''''
|
||||
URL = "https://www.powerdns.com/"
|
||||
Code = "pdns"
|
||||
Since = "v0.4.0"
|
||||
|
||||
Example = '''
|
||||
PDNS_API_URL=http://pdns-server:80/ \
|
||||
PDNS_API_KEY=xxxx \
|
||||
lego --email you@example.com --dns pdns --domains my.example.org run
|
||||
'''
|
||||
|
||||
Additional = '''
|
||||
## Information
|
||||
|
||||
Tested and confirmed to work with PowerDNS authoritative server 3.4.8 and 4.0.1. Refer to [PowerDNS documentation](https://doc.powerdns.com/md/httpapi/README/) instructions on how to enable the built-in API interface.
|
||||
|
||||
PowerDNS Notes:
|
||||
- PowerDNS API does not currently support SSL, therefore you should take care to ensure that traffic between lego and the PowerDNS API is over a trusted network, VPN etc.
|
||||
- In order to have the SOA serial automatically increment each time the `_acme-challenge` record is added/modified via the API, set `SOA-EDIT-API` to `INCEPTION-INCREMENT` for the zone in the `domainmetadata` table
|
||||
- Some PowerDNS servers doesn't have root API endpoints enabled and API version autodetection will not work. In that case version number can be defined using `PDNS_API_VERSION`.
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
PDNS_API_KEY = "API key"
|
||||
PDNS_API_URL = "API URL"
|
||||
[Configuration.Additional]
|
||||
PDNS_SERVER_NAME = "Name of the server in the URL, 'localhost' by default"
|
||||
PDNS_API_VERSION = "Skip API version autodetection and use the provided version number."
|
||||
PDNS_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
PDNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
PDNS_TTL = "The TTL of the TXT record used for the DNS challenge"
|
||||
PDNS_HTTP_TIMEOUT = "API request timeout"
|
||||
|
||||
[Links]
|
||||
API = "https://doc.powerdns.com/md/httpapi/README/"
|
10
vendor/github.com/go-acme/lego/v4/registration/registar.go
generated
vendored
10
vendor/github.com/go-acme/lego/v4/registration/registar.go
generated
vendored
@ -9,9 +9,11 @@ import (
|
||||
"github.com/go-acme/lego/v4/log"
|
||||
)
|
||||
|
||||
const mailTo = "mailto:"
|
||||
|
||||
// Resource represents all important information about a registration
|
||||
// of which the client needs to keep track itself.
|
||||
// WARNING: will be remove in the future (acme.ExtendedAccount), https://github.com/go-acme/lego/issues/855.
|
||||
// WARNING: will be removed in the future (acme.ExtendedAccount), https://github.com/go-acme/lego/issues/855.
|
||||
type Resource struct {
|
||||
Body acme.Account `json:"body,omitempty"`
|
||||
URI string `json:"uri,omitempty"`
|
||||
@ -52,7 +54,7 @@ func (r *Registrar) Register(options RegisterOptions) (*Resource, error) {
|
||||
|
||||
if r.user.GetEmail() != "" {
|
||||
log.Infof("acme: Registering account for %s", r.user.GetEmail())
|
||||
accMsg.Contact = []string{"mailto:" + r.user.GetEmail()}
|
||||
accMsg.Contact = []string{mailTo + r.user.GetEmail()}
|
||||
}
|
||||
|
||||
account, err := r.core.Accounts.New(accMsg)
|
||||
@ -76,7 +78,7 @@ func (r *Registrar) RegisterWithExternalAccountBinding(options RegisterEABOption
|
||||
|
||||
if r.user.GetEmail() != "" {
|
||||
log.Infof("acme: Registering account for %s", r.user.GetEmail())
|
||||
accMsg.Contact = []string{"mailto:" + r.user.GetEmail()}
|
||||
accMsg.Contact = []string{mailTo + r.user.GetEmail()}
|
||||
}
|
||||
|
||||
account, err := r.core.Accounts.NewEAB(accMsg, options.Kid, options.HmacEncoded)
|
||||
@ -128,7 +130,7 @@ func (r *Registrar) UpdateRegistration(options RegisterOptions) (*Resource, erro
|
||||
|
||||
if r.user.GetEmail() != "" {
|
||||
log.Infof("acme: Registering account for %s", r.user.GetEmail())
|
||||
accMsg.Contact = []string{"mailto:" + r.user.GetEmail()}
|
||||
accMsg.Contact = []string{mailTo + r.user.GetEmail()}
|
||||
}
|
||||
|
||||
accountURL := r.user.GetRegistration().URI
|
||||
|
2
vendor/github.com/go-jose/go-jose/v4/.gitignore
generated
vendored
Normal file
2
vendor/github.com/go-jose/go-jose/v4/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
jose-util/jose-util
|
||||
jose-util.t.err
|
53
vendor/github.com/go-jose/go-jose/v4/.golangci.yml
generated
vendored
Normal file
53
vendor/github.com/go-jose/go-jose/v4/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# https://github.com/golangci/golangci-lint
|
||||
|
||||
run:
|
||||
skip-files:
|
||||
- doc_test.go
|
||||
modules-download-mode: readonly
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
- goconst
|
||||
- lll
|
||||
- maligned
|
||||
- nakedret
|
||||
- scopelint
|
||||
- unparam
|
||||
- funlen # added in 1.18 (requires go-jose changes before it can be enabled)
|
||||
|
||||
linters-settings:
|
||||
gocyclo:
|
||||
min-complexity: 35
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
- text: "don't use ALL_CAPS in Go names"
|
||||
linters:
|
||||
- golint
|
||||
- text: "hardcoded credentials"
|
||||
linters:
|
||||
- gosec
|
||||
- text: "weak cryptographic primitive"
|
||||
linters:
|
||||
- gosec
|
||||
- path: json/
|
||||
linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- golint
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- unused
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- scopelint
|
||||
- path: jwk.go
|
||||
linters:
|
||||
- gocyclo
|
33
vendor/github.com/go-jose/go-jose/v4/.travis.yml
generated
vendored
Normal file
33
vendor/github.com/go-jose/go-jose/v4/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
language: go
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
go:
|
||||
- "1.13.x"
|
||||
- "1.14.x"
|
||||
- tip
|
||||
|
||||
before_script:
|
||||
- export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
before_install:
|
||||
- go get -u github.com/mattn/goveralls github.com/wadey/gocovmerge
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0
|
||||
- pip install cram --user
|
||||
|
||||
script:
|
||||
- go test -v -covermode=count -coverprofile=profile.cov .
|
||||
- go test -v -covermode=count -coverprofile=cryptosigner/profile.cov ./cryptosigner
|
||||
- go test -v -covermode=count -coverprofile=cipher/profile.cov ./cipher
|
||||
- go test -v -covermode=count -coverprofile=jwt/profile.cov ./jwt
|
||||
- go test -v ./json # no coverage for forked encoding/json package
|
||||
- golangci-lint run
|
||||
- cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util
|
||||
- cd ..
|
||||
|
||||
after_success:
|
||||
- gocovmerge *.cov */*.cov > merged.coverprofile
|
||||
- goveralls -coverprofile merged.coverprofile -service=travis-ci
|
96
vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md
generated
vendored
Normal file
96
vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
# v4.0.4
|
||||
|
||||
## Fixed
|
||||
|
||||
- Reverted "Allow unmarshalling JSONWebKeySets with unsupported key types" as a
|
||||
breaking change. See #136 / #137.
|
||||
|
||||
# v4.0.3
|
||||
|
||||
## Changed
|
||||
|
||||
- Allow unmarshalling JSONWebKeySets with unsupported key types (#130)
|
||||
- Document that OpaqueKeyEncrypter can't be implemented (for now) (#129)
|
||||
- Dependency updates
|
||||
|
||||
# v4.0.2
|
||||
|
||||
## Changed
|
||||
|
||||
- Improved documentation of Verify() to note that JSONWebKeySet is a supported
|
||||
argument type (#104)
|
||||
- Defined exported error values for missing x5c header and unsupported elliptic
|
||||
curves error cases (#117)
|
||||
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- An attacker could send a JWE containing compressed data that used large
|
||||
amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
|
||||
Those functions now return an error if the decompressed data would exceed
|
||||
250kB or 10x the compressed size (whichever is larger). Thanks to
|
||||
Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
|
||||
for reporting.
|
||||
|
||||
# v4.0.0
|
||||
|
||||
This release makes some breaking changes in order to more thoroughly
|
||||
address the vulnerabilities discussed in [Three New Attacks Against JSON Web
|
||||
Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
|
||||
token".
|
||||
|
||||
## Changed
|
||||
|
||||
- Limit JWT encryption types (exclude password or public key types) (#78)
|
||||
- Enforce minimum length for HMAC keys (#85)
|
||||
- jwt: match any audience in a list, rather than requiring all audiences (#81)
|
||||
- jwt: accept only Compact Serialization (#75)
|
||||
- jws: Add expected algorithms for signatures (#74)
|
||||
- Require specifying expected algorithms for ParseEncrypted,
|
||||
ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
|
||||
jwt.ParseSignedAndEncrypted (#69, #74)
|
||||
- Usually there is a small, known set of appropriate algorithms for a program
|
||||
to use and it's a mistake to allow unexpected algorithms. For instance the
|
||||
"billion hash attack" relies in part on programs accepting the PBES2
|
||||
encryption algorithm and doing the necessary work even if they weren't
|
||||
specifically configured to allow PBES2.
|
||||
- Revert "Strip padding off base64 strings" (#82)
|
||||
- The specs require base64url encoding without padding.
|
||||
- Minimum supported Go version is now 1.21
|
||||
|
||||
## Added
|
||||
|
||||
- ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
|
||||
- These allow parsing a specific serialization, as opposed to ParseSigned and
|
||||
ParseEncrypted, which try to automatically detect which serialization was
|
||||
provided. It's common to require a specific serialization for a specific
|
||||
protocol - for instance JWT requires Compact serialization.
|
||||
|
||||
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
||||
|
||||
# v3.0.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- DecryptMulti: handle decompression error (#19)
|
||||
|
||||
## Changed
|
||||
|
||||
- jwe/CompactSerialize: improve performance (#67)
|
||||
- Increase the default number of PBKDF2 iterations to 600k (#48)
|
||||
- Return the proper algorithm for ECDSA keys (#45)
|
||||
|
||||
## Added
|
||||
|
||||
- Add Thumbprint support for opaque signers (#38)
|
||||
|
||||
# v3.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- Security issue: an attacker specifying a large "p2c" value can cause
|
||||
JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
|
||||
amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
|
||||
disclosure and to Tom Tervoort for originally publishing the category of attack.
|
||||
https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
@ -9,6 +9,7 @@ sure all tests pass by running `go test`, and format your code with `go fmt`.
|
||||
We also recommend using `golint` and `errcheck`.
|
||||
|
||||
Before your code can be accepted into the project you must also sign the
|
||||
[Individual Contributor License Agreement][1].
|
||||
Individual Contributor License Agreement. We use [cla-assistant.io][1] and you
|
||||
will be prompted to sign once a pull request is opened.
|
||||
|
||||
[1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
|
||||
[1]: https://cla-assistant.io/
|
@ -1,10 +1,9 @@
|
||||
# Go JOSE
|
||||
# Go JOSE
|
||||
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v1)
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v2)
|
||||
[](https://raw.githubusercontent.com/square/go-jose/master/LICENSE)
|
||||
[](https://travis-ci.org/square/go-jose)
|
||||
[](https://coveralls.io/r/square/go-jose)
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
|
||||
[](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
|
||||
[](https://github.com/go-jose/go-jose/actions)
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. This includes support for JSON Web Encryption,
|
||||
@ -21,13 +20,13 @@ US maintained blocked list.
|
||||
## Overview
|
||||
|
||||
The implementation follows the
|
||||
[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||
[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||
[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519).
|
||||
[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||
[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||
[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
||||
Tables of supported algorithms are shown below. The library supports both
|
||||
the compact and full serialization formats, and has optional support for
|
||||
the compact and JWS/JWE JSON Serialization formats, and has optional support for
|
||||
multiple recipients. It also comes with a small command-line utility
|
||||
([`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util))
|
||||
([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util))
|
||||
for dealing with JOSE messages in a shell.
|
||||
|
||||
**Note**: We use a forked version of the `encoding/json` package from the Go
|
||||
@ -38,25 +37,22 @@ libraries in other languages.
|
||||
|
||||
### Versions
|
||||
|
||||
We use [gopkg.in](https://gopkg.in) for versioning.
|
||||
[Version 4](https://github.com/go-jose/go-jose)
|
||||
([branch](https://github.com/go-jose/go-jose/tree/main),
|
||||
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
|
||||
|
||||
[Version 2](https://gopkg.in/square/go-jose.v2)
|
||||
([branch](https://github.com/square/go-jose/tree/v2),
|
||||
[doc](https://godoc.org/gopkg.in/square/go-jose.v2)) is the current version:
|
||||
import "github.com/go-jose/go-jose/v4"
|
||||
|
||||
import "gopkg.in/square/go-jose.v2"
|
||||
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
|
||||
are still useable but not actively developed anymore.
|
||||
|
||||
The old `v1` branch ([go-jose.v1](https://gopkg.in/square/go-jose.v1)) will
|
||||
still receive backported bug fixes and security fixes, but otherwise
|
||||
development is frozen. All new feature development takes place on the `v2`
|
||||
branch. Version 2 also contains additional sub-packages such as the
|
||||
[jwt](https://godoc.org/gopkg.in/square/go-jose.v2/jwt) implementation
|
||||
contributed by [@shaxbee](https://github.com/shaxbee).
|
||||
Version 3, in this repo, is still receiving security fixes but not functionality
|
||||
updates.
|
||||
|
||||
### Supported algorithms
|
||||
|
||||
See below for a table of supported algorithms. Algorithm identifiers match
|
||||
the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518)
|
||||
the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
|
||||
standard where possible. The Godoc reference has a list of constants.
|
||||
|
||||
Key encryption | Algorithm identifier(s)
|
||||
@ -84,7 +80,7 @@ standard where possible. The Godoc reference has a list of constants.
|
||||
Content encryption | Algorithm identifier(s)
|
||||
:------------------------- | :------------------------------
|
||||
AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512
|
||||
AES-GCM | A128GCM, A192GCM, A256GCM
|
||||
AES-GCM | A128GCM, A192GCM, A256GCM
|
||||
|
||||
Compression | Algorithm identifiers(s)
|
||||
:------------------------- | -------------------------------
|
||||
@ -99,20 +95,20 @@ allows attaching a key id.
|
||||
|
||||
Algorithm(s) | Corresponding types
|
||||
:------------------------- | -------------------------------
|
||||
RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey)
|
||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://godoc.org/golang.org/x/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/golang.org/x/crypto/ed25519#PrivateKey)
|
||||
RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
|
||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
|
||||
AES, HMAC | []byte
|
||||
|
||||
<sup>1. Only available in version 2 of the package</sup>
|
||||
<sup>1. Only available in version 2 or later of the package</sup>
|
||||
|
||||
## Examples
|
||||
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v1)
|
||||
[](https://godoc.org/gopkg.in/square/go-jose.v2)
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
|
||||
|
||||
Examples can be found in the Godoc
|
||||
reference for this package. The
|
||||
[`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util)
|
||||
[`jose-util`](https://github.com/go-jose/go-jose/tree/v4/jose-util)
|
||||
subdirectory also contains a small command-line utility which might be useful
|
||||
as an example.
|
||||
as an example as well.
|
13
vendor/github.com/go-jose/go-jose/v4/SECURITY.md
generated
vendored
Normal file
13
vendor/github.com/go-jose/go-jose/v4/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
This document explains how to contact the Let's Encrypt security team to report security vulnerabilities.
|
||||
|
||||
## Supported Versions
|
||||
| Version | Supported |
|
||||
| ------- | ----------|
|
||||
| >= v3 | ✓ |
|
||||
| v2 | ✗ |
|
||||
| v1 | ✗ |
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email.
|
@ -20,6 +20,7 @@ import (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
@ -28,9 +29,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
josecipher "gopkg.in/square/go-jose.v2/cipher"
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
josecipher "github.com/go-jose/go-jose/v4/cipher"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// A generic RSA-based encrypter/verifier
|
||||
@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
|
||||
|
||||
switch alg {
|
||||
case RS256, RS384, RS512:
|
||||
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
|
||||
// random parameter is legacy and ignored, and it can be nil.
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
|
||||
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
||||
case PS256, PS384, PS512:
|
||||
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
||||
@ -413,28 +416,28 @@ func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||
epk, err := headers.getEPK()
|
||||
if err != nil {
|
||||
return nil, errors.New("square/go-jose: invalid epk header")
|
||||
return nil, errors.New("go-jose/go-jose: invalid epk header")
|
||||
}
|
||||
if epk == nil {
|
||||
return nil, errors.New("square/go-jose: missing epk header")
|
||||
return nil, errors.New("go-jose/go-jose: missing epk header")
|
||||
}
|
||||
|
||||
publicKey, ok := epk.Key.(*ecdsa.PublicKey)
|
||||
if publicKey == nil || !ok {
|
||||
return nil, errors.New("square/go-jose: invalid epk header")
|
||||
return nil, errors.New("go-jose/go-jose: invalid epk header")
|
||||
}
|
||||
|
||||
if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
|
||||
return nil, errors.New("square/go-jose: invalid public key in epk header")
|
||||
return nil, errors.New("go-jose/go-jose: invalid public key in epk header")
|
||||
}
|
||||
|
||||
apuData, err := headers.getAPU()
|
||||
if err != nil {
|
||||
return nil, errors.New("square/go-jose: invalid apu header")
|
||||
return nil, errors.New("go-jose/go-jose: invalid apu header")
|
||||
}
|
||||
apvData, err := headers.getAPV()
|
||||
if err != nil {
|
||||
return nil, errors.New("square/go-jose: invalid apv header")
|
||||
return nil, errors.New("go-jose/go-jose: invalid apv header")
|
||||
}
|
||||
|
||||
deriveKey := func(algID string, size int) []byte {
|
||||
@ -489,7 +492,7 @@ func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
|
||||
}
|
||||
ok := ed25519.Verify(ctx.publicKey, payload, signature)
|
||||
if !ok {
|
||||
return errors.New("square/go-jose: ed25519 signature failed to verify")
|
||||
return errors.New("go-jose/go-jose: ed25519 signature failed to verify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -513,7 +516,7 @@ func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm)
|
||||
|
||||
curveBits := ctx.privateKey.Curve.Params().BitSize
|
||||
if expectedBitSize != curveBits {
|
||||
return Signature{}, fmt.Errorf("square/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
|
||||
return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
@ -571,7 +574,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
|
||||
}
|
||||
|
||||
if len(signature) != 2*keySize {
|
||||
return fmt.Errorf("square/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
|
||||
return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
@ -585,7 +588,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
|
||||
|
||||
match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
|
||||
if !match {
|
||||
return errors.New("square/go-jose: ecdsa signature failed to verify")
|
||||
return errors.New("go-jose/go-jose: ecdsa signature failed to verify")
|
||||
}
|
||||
|
||||
return nil
|
@ -101,23 +101,23 @@ func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
// Open decrypts and authenticates the ciphertext.
|
||||
func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
if len(ciphertext) < ctx.authtagBytes {
|
||||
return nil, errors.New("square/go-jose: invalid ciphertext (too short)")
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)")
|
||||
}
|
||||
|
||||
offset := len(ciphertext) - ctx.authtagBytes
|
||||
expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset])
|
||||
match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:])
|
||||
if match != 1 {
|
||||
return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)")
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)")
|
||||
}
|
||||
|
||||
cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce)
|
||||
|
||||
// Make copy of ciphertext buffer, don't want to modify in place
|
||||
buffer := append([]byte{}, []byte(ciphertext[:offset])...)
|
||||
buffer := append([]byte{}, ciphertext[:offset]...)
|
||||
|
||||
if len(buffer)%ctx.blockCipher.BlockSize() > 0 {
|
||||
return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)")
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)")
|
||||
}
|
||||
|
||||
cbc.CryptBlocks(buffer, buffer)
|
||||
@ -150,7 +150,7 @@ func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
|
||||
return hmac.Sum(nil)[:ctx.authtagBytes]
|
||||
}
|
||||
|
||||
// resize ensures the the given slice has a capacity of at least n bytes.
|
||||
// resize ensures that the given slice has a capacity of at least n bytes.
|
||||
// If the capacity of the slice is less than n, a new slice is allocated
|
||||
// and the existing data will be copied.
|
||||
func resize(in []byte, n uint64) (head, tail []byte) {
|
||||
@ -177,19 +177,19 @@ func padBuffer(buffer []byte, blockSize int) []byte {
|
||||
// Remove padding
|
||||
func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
|
||||
if len(buffer)%blockSize != 0 {
|
||||
return nil, errors.New("square/go-jose: invalid padding")
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
last := buffer[len(buffer)-1]
|
||||
count := int(last)
|
||||
|
||||
if count == 0 || count > blockSize || count > len(buffer) {
|
||||
return nil, errors.New("square/go-jose: invalid padding")
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
padding := bytes.Repeat([]byte{last}, count)
|
||||
if !bytes.HasSuffix(buffer, padding) {
|
||||
return nil, errors.New("square/go-jose: invalid padding")
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
return buffer[:len(buffer)-count], nil
|
@ -28,7 +28,7 @@ var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
|
||||
// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher.
|
||||
func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
|
||||
if len(cek)%8 != 0 {
|
||||
return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks")
|
||||
return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
|
||||
}
|
||||
|
||||
n := len(cek) / 8
|
||||
@ -51,7 +51,7 @@ func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
|
||||
binary.BigEndian.PutUint64(tBytes, uint64(t+1))
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
buffer[i] = buffer[i] ^ tBytes[i]
|
||||
buffer[i] ^= tBytes[i]
|
||||
}
|
||||
copy(r[t%n], buffer[8:])
|
||||
}
|
||||
@ -68,7 +68,7 @@ func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
|
||||
// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher.
|
||||
func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
|
||||
if len(ciphertext)%8 != 0 {
|
||||
return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks")
|
||||
return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
|
||||
}
|
||||
|
||||
n := (len(ciphertext) / 8) - 1
|
||||
@ -87,7 +87,7 @@ func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
|
||||
binary.BigEndian.PutUint64(tBytes, uint64(t+1))
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
buffer[i] = buffer[i] ^ tBytes[i]
|
||||
buffer[i] ^= tBytes[i]
|
||||
}
|
||||
copy(buffer[8:], r[t%n])
|
||||
|
||||
@ -97,7 +97,7 @@ func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 {
|
||||
return nil, errors.New("square/go-jose: failed to unwrap key")
|
||||
return nil, errors.New("go-jose/go-jose: failed to unwrap key")
|
||||
}
|
||||
|
||||
out := make([]byte, n*8)
|
@ -21,9 +21,8 @@ import (
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
||||
@ -76,14 +75,24 @@ type recipientKeyInfo struct {
|
||||
type EncrypterOptions struct {
|
||||
Compression CompressionAlgorithm
|
||||
|
||||
// Optional map of additional keys to be inserted into the protected header
|
||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||
// additional values here. All values must be JSON-serializable.
|
||||
// Optional map of name/value pairs to be inserted into the protected
|
||||
// header of a JWS object. Some specifications which make use of
|
||||
// JWS require additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary. It returns itself and so can be used in a fluent style.
|
||||
// if necessary, and returns the updated EncrypterOptions.
|
||||
//
|
||||
// The v parameter will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
||||
if eo.ExtraHeaders == nil {
|
||||
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
@ -111,7 +120,17 @@ func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
|
||||
// default of 100000 will be used for the count and a 128-bit random salt will
|
||||
// be generated.
|
||||
type Recipient struct {
|
||||
Algorithm KeyAlgorithm
|
||||
Algorithm KeyAlgorithm
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyEncrypter interface
|
||||
//
|
||||
// The type of Key must match the value of Algorithm.
|
||||
Key interface{}
|
||||
KeyID string
|
||||
PBES2Count int
|
||||
@ -150,16 +169,17 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||
switch rcpt.Algorithm {
|
||||
case DIRECT:
|
||||
// Direct encryption mode must be treated differently
|
||||
if reflect.TypeOf(rawKey) != reflect.TypeOf([]byte{}) {
|
||||
keyBytes, ok := rawKey.([]byte)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if encrypter.cipher.keySize() != len(rawKey.([]byte)) {
|
||||
if encrypter.cipher.keySize() != len(keyBytes) {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
encrypter.keyGenerator = staticKeyGenerator{
|
||||
key: rawKey.([]byte),
|
||||
key: keyBytes,
|
||||
}
|
||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, rawKey.([]byte))
|
||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
@ -168,16 +188,16 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions)
|
||||
return encrypter, nil
|
||||
case ECDH_ES:
|
||||
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
|
||||
typeOf := reflect.TypeOf(rawKey)
|
||||
if typeOf != reflect.TypeOf(&ecdsa.PublicKey{}) {
|
||||
keyDSA, ok := rawKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
encrypter.keyGenerator = ecKeyGenerator{
|
||||
size: encrypter.cipher.keySize(),
|
||||
algID: string(enc),
|
||||
publicKey: rawKey.(*ecdsa.PublicKey),
|
||||
publicKey: keyDSA,
|
||||
}
|
||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, rawKey.(*ecdsa.PublicKey))
|
||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
@ -201,8 +221,8 @@ func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *Encrypter
|
||||
if cipher == nil {
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
if rcpts == nil || len(rcpts) == 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: recipients is nil or empty")
|
||||
if len(rcpts) == 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty")
|
||||
}
|
||||
|
||||
encrypter := &genericEncrypter{
|
||||
@ -216,6 +236,7 @@ func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *Encrypter
|
||||
|
||||
if opts != nil {
|
||||
encrypter.compressionAlg = opts.Compression
|
||||
encrypter.extraHeaders = opts.ExtraHeaders
|
||||
}
|
||||
|
||||
for _, recipient := range rcpts {
|
||||
@ -233,7 +254,7 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
|
||||
|
||||
switch recipient.Algorithm {
|
||||
case DIRECT, ECDH_ES:
|
||||
return fmt.Errorf("square/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
|
||||
return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
|
||||
}
|
||||
|
||||
recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key)
|
||||
@ -269,9 +290,8 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
|
||||
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
||||
recipient.keyID = encryptionKey.KeyID
|
||||
return recipient, err
|
||||
}
|
||||
if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok {
|
||||
return newOpaqueKeyEncrypter(alg, encrypter)
|
||||
case OpaqueKeyEncrypter:
|
||||
return newOpaqueKeyEncrypter(alg, encryptionKey)
|
||||
}
|
||||
return recipientKeyInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
@ -299,11 +319,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
|
||||
return newDecrypter(decryptionKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newDecrypter(decryptionKey.Key)
|
||||
case OpaqueKeyDecrypter:
|
||||
return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok {
|
||||
return &opaqueKeyDecrypter{decrypter: okd}, nil
|
||||
}
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
// Implementation of encrypt method producing a JWE object.
|
||||
@ -325,7 +345,7 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
|
||||
obj.recipients = make([]recipientInfo, len(ctx.recipients))
|
||||
|
||||
if len(ctx.recipients) == 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: no recipients to encrypt to")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to")
|
||||
}
|
||||
|
||||
cek, headers, err := ctx.keyGenerator.genKey()
|
||||
@ -402,33 +422,55 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt and validate the object and return the plaintext. Note that this
|
||||
// function does not support multi-recipient, if you desire multi-recipient
|
||||
// Decrypt and validate the object and return the plaintext. This
|
||||
// function does not support multi-recipient. If you desire multi-recipient
|
||||
// decryption use DecryptMulti instead.
|
||||
//
|
||||
// The decryptionKey argument must contain a private or symmetric key
|
||||
// and must have one of these types:
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - *JSONWebKeySet
|
||||
// - JSONWebKeySet
|
||||
// - []byte (a symmetric key)
|
||||
// - string (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyDecrypter interface.
|
||||
//
|
||||
// Note that ed25519 is only available for signatures, not encryption, so is
|
||||
// not an option here.
|
||||
//
|
||||
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||
// data would be >250kB or >10x the size of the compressed data, whichever is larger.
|
||||
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
|
||||
headers := obj.mergedHeaders(nil)
|
||||
|
||||
if len(obj.recipients) > 1 {
|
||||
return nil, errors.New("square/go-jose: too many recipients in payload; expecting only one")
|
||||
return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one")
|
||||
}
|
||||
|
||||
critical, err := headers.getCritical()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid crit header")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
|
||||
}
|
||||
|
||||
if len(critical) > 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
|
||||
}
|
||||
|
||||
decrypter, err := newDecrypter(decryptionKey)
|
||||
key, err := tryJWKS(decryptionKey, obj.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decrypter, err := newDecrypter(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cipher := getContentCipher(headers.getEncryption())
|
||||
if cipher == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
|
||||
}
|
||||
|
||||
generator := randomKeyGenerator{
|
||||
@ -460,28 +502,41 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return plaintext, err
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// DecryptMulti decrypts and validates the object and returns the plaintexts,
|
||||
// with support for multiple recipients. It returns the index of the recipient
|
||||
// for which the decryption was successful, the merged headers for that recipient,
|
||||
// and the plaintext.
|
||||
//
|
||||
// The decryptionKey argument must have one of the types allowed for the
|
||||
// decryptionKey argument of Decrypt().
|
||||
//
|
||||
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||
// data would be >250kB or >3x the size of the compressed data, whichever is larger.
|
||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||
globalHeaders := obj.mergedHeaders(nil)
|
||||
|
||||
critical, err := globalHeaders.getCritical()
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: invalid crit header")
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
|
||||
}
|
||||
|
||||
if len(critical) > 0 {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header")
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
|
||||
}
|
||||
|
||||
decrypter, err := newDecrypter(decryptionKey)
|
||||
key, err := tryJWKS(decryptionKey, obj.Header)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, err
|
||||
}
|
||||
decrypter, err := newDecrypter(key)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, err
|
||||
}
|
||||
@ -489,7 +544,7 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||
encryption := globalHeaders.getEncryption()
|
||||
cipher := getContentCipher(encryption)
|
||||
if cipher == nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(encryption))
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption))
|
||||
}
|
||||
|
||||
generator := randomKeyGenerator{
|
||||
@ -523,18 +578,21 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||
}
|
||||
}
|
||||
|
||||
if plaintext == nil || err != nil {
|
||||
if plaintext == nil {
|
||||
return -1, Header{}, nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
sanitized, err := headers.sanitized()
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("square/go-jose: failed to sanitize header: %v", err)
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err)
|
||||
}
|
||||
|
||||
return index, sanitized, plaintext, err
|
@ -15,13 +15,11 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. It implements encryption and signing based on
|
||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON
|
||||
Web Token support available in a sub-package. The library supports both the
|
||||
compact and full serialization formats, and has optional support for multiple
|
||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
|
||||
Token support available in a sub-package. The library supports both the compact
|
||||
and JWS/JWE JSON Serialization formats, and has optional support for multiple
|
||||
recipients.
|
||||
|
||||
*/
|
||||
package jose
|
@ -21,12 +21,13 @@ import (
|
||||
"compress/flate"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// Helper function to serialize known-good objects.
|
||||
@ -41,7 +42,7 @@ func mustSerializeJSON(value interface{}) []byte {
|
||||
// MarshalJSON will happily serialize it as the top-level value "null". If
|
||||
// that value is then embedded in another operation, for instance by being
|
||||
// base64-encoded and fed as input to a signing algorithm
|
||||
// (https://github.com/square/go-jose/issues/22), the result will be
|
||||
// (https://github.com/go-jose/go-jose/issues/22), the result will be
|
||||
// incorrect. Because this method is intended for known-good objects, and a nil
|
||||
// pointer is not a known-good object, we are free to panic in this case.
|
||||
// Note: It's not possible to directly check whether the data pointed at by an
|
||||
@ -85,7 +86,7 @@ func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Compress with DEFLATE
|
||||
// deflate compresses the input.
|
||||
func deflate(input []byte) ([]byte, error) {
|
||||
output := new(bytes.Buffer)
|
||||
|
||||
@ -97,15 +98,24 @@ func deflate(input []byte) ([]byte, error) {
|
||||
return output.Bytes(), err
|
||||
}
|
||||
|
||||
// Decompress with DEFLATE
|
||||
// inflate decompresses the input.
|
||||
//
|
||||
// Errors if the decompressed data would be >250kB or >10x the size of the
|
||||
// compressed data, whichever is larger.
|
||||
func inflate(input []byte) ([]byte, error) {
|
||||
output := new(bytes.Buffer)
|
||||
reader := flate.NewReader(bytes.NewBuffer(input))
|
||||
|
||||
_, err := io.Copy(output, reader)
|
||||
if err != nil {
|
||||
maxCompressedSize := max(250_000, 10*int64(len(input)))
|
||||
|
||||
limit := maxCompressedSize + 1
|
||||
n, err := io.CopyN(output, reader, limit)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
if n == limit {
|
||||
return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
|
||||
}
|
||||
|
||||
err = reader.Close()
|
||||
return output.Bytes(), err
|
||||
@ -127,7 +137,7 @@ func newBuffer(data []byte) *byteBuffer {
|
||||
|
||||
func newFixedSizeBuffer(data []byte, length int) *byteBuffer {
|
||||
if len(data) > length {
|
||||
panic("square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
|
||||
panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
|
||||
}
|
||||
pad := make([]byte, length-len(data))
|
||||
return newBuffer(append(pad, data...))
|
||||
@ -183,3 +193,36 @@ func (b byteBuffer) bigInt() *big.Int {
|
||||
func (b byteBuffer) toInt() int {
|
||||
return int(b.bigInt().Int64())
|
||||
}
|
||||
|
||||
func base64EncodeLen(sl []byte) int {
|
||||
return base64.RawURLEncoding.EncodedLen(len(sl))
|
||||
}
|
||||
|
||||
func base64JoinWithDots(inputs ...[]byte) string {
|
||||
if len(inputs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Count of dots.
|
||||
totalCount := len(inputs) - 1
|
||||
|
||||
for _, input := range inputs {
|
||||
totalCount += base64EncodeLen(input)
|
||||
}
|
||||
|
||||
out := make([]byte, totalCount)
|
||||
startEncode := 0
|
||||
for i, input := range inputs {
|
||||
base64.RawURLEncoding.Encode(out[startEncode:], input)
|
||||
|
||||
if i == len(inputs)-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
startEncode += base64EncodeLen(input)
|
||||
out[startEncode] = '.'
|
||||
startEncode++
|
||||
}
|
||||
|
||||
return string(out)
|
||||
}
|
@ -13,6 +13,7 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -74,14 +75,13 @@ import (
|
||||
//
|
||||
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
||||
// by setting that Go value to nil. Because null is often used in JSON to mean
|
||||
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
|
||||
// “not present,” unmarshaling a JSON null into any other Go type has no effect
|
||||
// on the value and produces no error.
|
||||
//
|
||||
// When unmarshaling quoted strings, invalid UTF-8 or
|
||||
// invalid UTF-16 surrogate pairs are not treated as an error.
|
||||
// Instead, they are replaced by the Unicode replacement
|
||||
// character U+FFFD.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
// Check for well-formedness.
|
||||
// Avoids filling out half a data structure
|
||||
@ -245,6 +245,18 @@ func isValidNumber(s string) bool {
|
||||
return s == ""
|
||||
}
|
||||
|
||||
type NumberUnmarshalType int
|
||||
|
||||
const (
|
||||
// unmarshal a JSON number into an interface{} as a float64
|
||||
UnmarshalFloat NumberUnmarshalType = iota
|
||||
// unmarshal a JSON number into an interface{} as a `json.Number`
|
||||
UnmarshalJSONNumber
|
||||
// unmarshal a JSON number into an interface{} as a int64
|
||||
// if value is an integer otherwise float64
|
||||
UnmarshalIntOrFloat
|
||||
)
|
||||
|
||||
// decodeState represents the state while decoding a JSON value.
|
||||
type decodeState struct {
|
||||
data []byte
|
||||
@ -252,7 +264,7 @@ type decodeState struct {
|
||||
scan scanner
|
||||
nextscan scanner // for calls to nextValue
|
||||
savedError error
|
||||
useNumber bool
|
||||
numberType NumberUnmarshalType
|
||||
}
|
||||
|
||||
// errPhase is used for errors that should not happen unless
|
||||
@ -723,17 +735,38 @@ func (d *decodeState) literal(v reflect.Value) {
|
||||
d.literalStore(d.data[start:d.off], v, false)
|
||||
}
|
||||
|
||||
// convertNumber converts the number literal s to a float64 or a Number
|
||||
// depending on the setting of d.useNumber.
|
||||
// convertNumber converts the number literal s to a float64, int64 or a Number
|
||||
// depending on d.numberDecodeType.
|
||||
func (d *decodeState) convertNumber(s string) (interface{}, error) {
|
||||
if d.useNumber {
|
||||
switch d.numberType {
|
||||
|
||||
case UnmarshalJSONNumber:
|
||||
return Number(s), nil
|
||||
case UnmarshalIntOrFloat:
|
||||
v, err := strconv.ParseInt(s, 10, 64)
|
||||
if err == nil {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// tries to parse integer number in scientific notation
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
|
||||
}
|
||||
|
||||
// if it has no decimal value use int64
|
||||
if fi, fd := math.Modf(f); fd == 0.0 {
|
||||
return int64(fi), nil
|
||||
}
|
||||
return f, nil
|
||||
default:
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
|
||||
}
|
||||
return f, nil
|
||||
|
||||
}
|
||||
|
||||
var numberType = reflect.TypeOf(Number(""))
|
@ -58,6 +58,7 @@ import (
|
||||
// becomes a member of the object unless
|
||||
// - the field's tag is "-", or
|
||||
// - the field is empty and its tag specifies the "omitempty" option.
|
||||
//
|
||||
// The empty values are false, 0, any
|
||||
// nil pointer or interface value, and any array, slice, map, or string of
|
||||
// length zero. The object's default key string is the struct field name
|
||||
@ -65,28 +66,28 @@ import (
|
||||
// the struct field's tag value is the key name, followed by an optional comma
|
||||
// and options. Examples:
|
||||
//
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
//
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
//
|
||||
// The "string" option signals that a field is stored as JSON inside a
|
||||
// JSON-encoded string. It applies only to fields of string, floating point,
|
||||
// integer, or boolean types. This extra level of encoding is sometimes used
|
||||
// when communicating with JavaScript programs:
|
||||
//
|
||||
// Int64String int64 `json:",string"`
|
||||
// Int64String int64 `json:",string"`
|
||||
//
|
||||
// The key name will be used if it's a non-empty string consisting of
|
||||
// only Unicode letters, digits, dollar signs, percent signs, hyphens,
|
||||
@ -133,7 +134,6 @@ import (
|
||||
// JSON cannot represent cyclic data structures and Marshal does not
|
||||
// handle them. Passing cyclic structures to Marshal will result in
|
||||
// an infinite recursion.
|
||||
//
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
e := &encodeState{}
|
||||
err := e.marshal(v)
|
||||
@ -648,7 +648,7 @@ func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
|
||||
// for large buffers, avoid unnecessary extra temporary
|
||||
// buffer space.
|
||||
enc := base64.NewEncoder(base64.StdEncoding, e)
|
||||
enc.Write(s)
|
||||
_, _ = enc.Write(s)
|
||||
enc.Close()
|
||||
}
|
||||
e.WriteByte('"')
|
@ -31,9 +31,14 @@ func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
// Deprecated: Use `SetNumberType` instead
|
||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number instead of as a float64.
|
||||
func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
|
||||
func (dec *Decoder) UseNumber() { dec.d.numberType = UnmarshalJSONNumber }
|
||||
|
||||
// SetNumberType causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number, float64 or int64 depending on `t` enum value.
|
||||
func (dec *Decoder) SetNumberType(t NumberUnmarshalType) { dec.d.numberType = t }
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v.
|
||||
@ -235,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil)
|
||||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token interface{}
|
||||
|
||||
const (
|
149
vendor/gopkg.in/square/go-jose.v2/jwe.go → vendor/github.com/go-jose/go-jose/v4/jwe.go
generated
vendored
149
vendor/gopkg.in/square/go-jose.v2/jwe.go → vendor/github.com/go-jose/go-jose/v4/jwe.go
generated
vendored
@ -18,10 +18,11 @@ package jose
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
||||
@ -86,11 +87,12 @@ func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader {
|
||||
func (obj JSONWebEncryption) computeAuthData() []byte {
|
||||
var protected string
|
||||
|
||||
if obj.original != nil && obj.original.Protected != nil {
|
||||
switch {
|
||||
case obj.original != nil && obj.original.Protected != nil:
|
||||
protected = obj.original.Protected.base64()
|
||||
} else if obj.protected != nil {
|
||||
case obj.protected != nil:
|
||||
protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected)))
|
||||
} else {
|
||||
default:
|
||||
protected = ""
|
||||
}
|
||||
|
||||
@ -103,29 +105,75 @@ func (obj JSONWebEncryption) computeAuthData() []byte {
|
||||
return output
|
||||
}
|
||||
|
||||
// ParseEncrypted parses an encrypted message in compact or full serialization format.
|
||||
func ParseEncrypted(input string) (*JSONWebEncryption, error) {
|
||||
input = stripWhitespace(input)
|
||||
if strings.HasPrefix(input, "{") {
|
||||
return parseEncryptedFull(input)
|
||||
func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool {
|
||||
for _, algorithm := range haystack {
|
||||
if algorithm == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return parseEncryptedCompact(input)
|
||||
return false
|
||||
}
|
||||
|
||||
// parseEncryptedFull parses a message in compact format.
|
||||
func parseEncryptedFull(input string) (*JSONWebEncryption, error) {
|
||||
func containsContentEncryption(haystack []ContentEncryption, needle ContentEncryption) bool {
|
||||
for _, algorithm := range haystack {
|
||||
if algorithm == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseEncrypted parses an encrypted message in JWE Compact or JWE JSON Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
|
||||
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
|
||||
//
|
||||
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
|
||||
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in
|
||||
// parsed data must contain a value that is present in the corresponding parameter. That
|
||||
// includes the protected and unprotected headers as well as all recipients. To accept
|
||||
// multiple algorithms, pass a slice of all the algorithms you want to accept.
|
||||
func ParseEncrypted(input string,
|
||||
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||
contentEncryption []ContentEncryption,
|
||||
) (*JSONWebEncryption, error) {
|
||||
input = stripWhitespace(input)
|
||||
if strings.HasPrefix(input, "{") {
|
||||
return ParseEncryptedJSON(input, keyEncryptionAlgorithms, contentEncryption)
|
||||
}
|
||||
|
||||
return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption)
|
||||
}
|
||||
|
||||
// ParseEncryptedJSON parses a message in JWE JSON Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
|
||||
func ParseEncryptedJSON(
|
||||
input string,
|
||||
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||
contentEncryption []ContentEncryption,
|
||||
) (*JSONWebEncryption, error) {
|
||||
var parsed rawJSONWebEncryption
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parsed.sanitized()
|
||||
return parsed.sanitized(keyEncryptionAlgorithms, contentEncryption)
|
||||
}
|
||||
|
||||
// sanitized produces a cleaned-up JWE object from the raw JSON.
|
||||
func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
func (parsed *rawJSONWebEncryption) sanitized(
|
||||
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||
contentEncryption []ContentEncryption,
|
||||
) (*JSONWebEncryption, error) {
|
||||
if len(keyEncryptionAlgorithms) == 0 {
|
||||
return nil, errors.New("go-jose/go-jose: no key algorithms provided")
|
||||
}
|
||||
if len(contentEncryption) == 0 {
|
||||
return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided")
|
||||
}
|
||||
|
||||
obj := &JSONWebEncryption{
|
||||
original: parsed,
|
||||
unprotected: parsed.Unprotected,
|
||||
@ -146,7 +194,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +204,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
mergedHeaders := obj.mergedHeaders(nil)
|
||||
obj.Header, err = mergedHeaders.sanitized()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
|
||||
}
|
||||
|
||||
if len(parsed.Recipients) == 0 {
|
||||
@ -184,10 +232,31 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
}
|
||||
}
|
||||
|
||||
for _, recipient := range obj.recipients {
|
||||
for i, recipient := range obj.recipients {
|
||||
headers := obj.mergedHeaders(&recipient)
|
||||
if headers.getAlgorithm() == "" || headers.getEncryption() == "" {
|
||||
return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers")
|
||||
if headers.getAlgorithm() == "" {
|
||||
return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "alg"`, i)
|
||||
}
|
||||
if headers.getEncryption() == "" {
|
||||
return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "enc"`, i)
|
||||
}
|
||||
err := validateAlgEnc(headers, keyEncryptionAlgorithms, contentEncryption)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: recipient %d: %s", i, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if obj.protected != nil {
|
||||
err := validateAlgEnc(*obj.protected, keyEncryptionAlgorithms, contentEncryption)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: protected header: %s", err)
|
||||
}
|
||||
}
|
||||
if obj.unprotected != nil {
|
||||
err := validateAlgEnc(*obj.unprotected, keyEncryptionAlgorithms, contentEncryption)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unprotected header: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,11 +268,29 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// parseEncryptedCompact parses a message in compact format.
|
||||
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
|
||||
func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncryption []ContentEncryption) error {
|
||||
alg := headers.getAlgorithm()
|
||||
enc := headers.getEncryption()
|
||||
if alg != "" && !containsKeyAlgorithm(keyAlgorithms, alg) {
|
||||
return fmt.Errorf("unexpected key algorithm %q; expected %q", alg, keyAlgorithms)
|
||||
}
|
||||
if alg != "" && !containsContentEncryption(contentEncryption, enc) {
|
||||
return fmt.Errorf("unexpected content encryption algorithm %q; expected %q", enc, contentEncryption)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseEncryptedCompact parses a message in JWE Compact Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
|
||||
func ParseEncryptedCompact(
|
||||
input string,
|
||||
keyAlgorithms []KeyAlgorithm,
|
||||
contentEncryption []ContentEncryption,
|
||||
) (*JSONWebEncryption, error) {
|
||||
parts := strings.Split(input, ".")
|
||||
if len(parts) != 5 {
|
||||
return nil, fmt.Errorf("square/go-jose: compact JWE format must have five parts")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
|
||||
}
|
||||
|
||||
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||
@ -239,7 +326,7 @@ func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
|
||||
Tag: newBuffer(tag),
|
||||
}
|
||||
|
||||
return raw.sanitized()
|
||||
return raw.sanitized(keyAlgorithms, contentEncryption)
|
||||
}
|
||||
|
||||
// CompactSerialize serializes an object using the compact serialization format.
|
||||
@ -251,13 +338,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
|
||||
|
||||
serializedProtected := mustSerializeJSON(obj.protected)
|
||||
|
||||
return fmt.Sprintf(
|
||||
"%s.%s.%s.%s.%s",
|
||||
base64.RawURLEncoding.EncodeToString(serializedProtected),
|
||||
base64.RawURLEncoding.EncodeToString(obj.recipients[0].encryptedKey),
|
||||
base64.RawURLEncoding.EncodeToString(obj.iv),
|
||||
base64.RawURLEncoding.EncodeToString(obj.ciphertext),
|
||||
base64.RawURLEncoding.EncodeToString(obj.tag)), nil
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
obj.recipients[0].encryptedKey,
|
||||
obj.iv,
|
||||
obj.ciphertext,
|
||||
obj.tag,
|
||||
), nil
|
||||
}
|
||||
|
||||
// FullSerialize serializes an object using the full JSON serialization format.
|
167
vendor/gopkg.in/square/go-jose.v2/jwk.go → vendor/github.com/go-jose/go-jose/v4/jwk.go
generated
vendored
167
vendor/gopkg.in/square/go-jose.v2/jwk.go → vendor/github.com/go-jose/go-jose/v4/jwk.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
@ -34,9 +35,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
|
||||
@ -63,14 +62,26 @@ type rawJSONWebKey struct {
|
||||
Qi *byteBuffer `json:"qi,omitempty"`
|
||||
// Certificates
|
||||
X5c []string `json:"x5c,omitempty"`
|
||||
X5u *url.URL `json:"x5u,omitempty"`
|
||||
X5u string `json:"x5u,omitempty"`
|
||||
X5tSHA1 string `json:"x5t,omitempty"`
|
||||
X5tSHA256 string `json:"x5t#S256,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebKey represents a public or private key in JWK format.
|
||||
// JSONWebKey represents a public or private key in JWK format. It can be
|
||||
// marshaled into JSON and unmarshaled from JSON.
|
||||
type JSONWebKey struct {
|
||||
// Cryptographic key, can be a symmetric or asymmetric key.
|
||||
// Key is the Go in-memory representation of this key. It must have one
|
||||
// of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PublicKey
|
||||
// - *rsa.PrivateKey
|
||||
// - []byte (a symmetric key)
|
||||
//
|
||||
// When marshaling this JSONWebKey into JSON, the "kty" header parameter
|
||||
// will be automatically set based on the type of this field.
|
||||
Key interface{}
|
||||
// Key identifier, parsed from `kid` header.
|
||||
KeyID string
|
||||
@ -110,7 +121,7 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
case []byte:
|
||||
raw, err = fromSymmetricKey(key)
|
||||
default:
|
||||
return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -129,13 +140,13 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
|
||||
if x5tSHA1Len > 0 {
|
||||
if x5tSHA1Len != sha1.Size {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
|
||||
}
|
||||
raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
|
||||
}
|
||||
if x5tSHA256Len > 0 {
|
||||
if x5tSHA256Len != sha256.Size {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
|
||||
}
|
||||
raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
|
||||
}
|
||||
@ -149,14 +160,16 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
|
||||
|
||||
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
|
||||
return nil, errors.New("square/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
|
||||
return nil, errors.New("go-jose/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
|
||||
}
|
||||
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
|
||||
return nil, errors.New("square/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
|
||||
return nil, errors.New("go-jose/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
|
||||
}
|
||||
}
|
||||
|
||||
raw.X5u = k.CertificatesURL
|
||||
if k.CertificatesURL != nil {
|
||||
raw.X5u = k.CertificatesURL.String()
|
||||
}
|
||||
|
||||
return json.Marshal(raw)
|
||||
}
|
||||
@ -171,7 +184,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
|
||||
certs, err := parseCertificateChain(raw.X5c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("square/go-jose: failed to unmarshal x5c field: %s", err)
|
||||
return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err)
|
||||
}
|
||||
|
||||
var key interface{}
|
||||
@ -211,7 +224,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
}
|
||||
case "oct":
|
||||
if certPub != nil {
|
||||
return errors.New("square/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
|
||||
}
|
||||
key, err = raw.symmetricKey()
|
||||
case "OKP":
|
||||
@ -226,10 +239,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
keyPub = key
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv)
|
||||
err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty)
|
||||
err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -238,19 +251,24 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
|
||||
if certPub != nil && keyPub != nil {
|
||||
if !reflect.DeepEqual(certPub, keyPub) {
|
||||
return errors.New("square/go-jose: invalid JWK, public keys in key and x5c fields to not match")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
|
||||
}
|
||||
}
|
||||
|
||||
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
|
||||
|
||||
k.CertificatesURL = raw.X5u
|
||||
if raw.X5u != "" {
|
||||
k.CertificatesURL, err = url.Parse(raw.X5u)
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, x5u header is invalid URL: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// x5t parameters are base64url-encoded SHA thumbprints
|
||||
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
|
||||
x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
|
||||
if err != nil {
|
||||
return errors.New("square/go-jose: invalid JWK, x5t header has invalid encoding")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
|
||||
}
|
||||
|
||||
// RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex,
|
||||
@ -260,7 +278,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
if len(x5tSHA1bytes) == 2*sha1.Size {
|
||||
hx, err := hex.DecodeString(string(x5tSHA1bytes))
|
||||
if err != nil {
|
||||
return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
|
||||
|
||||
}
|
||||
x5tSHA1bytes = hx
|
||||
@ -270,13 +288,13 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
|
||||
x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
|
||||
if err != nil {
|
||||
return errors.New("square/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
|
||||
}
|
||||
|
||||
if len(x5tSHA256bytes) == 2*sha256.Size {
|
||||
hx256, err := hex.DecodeString(string(x5tSHA256bytes))
|
||||
if err != nil {
|
||||
return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
|
||||
}
|
||||
x5tSHA256bytes = hx256
|
||||
}
|
||||
@ -286,10 +304,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
x5tSHA1Len := len(k.CertificateThumbprintSHA1)
|
||||
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
|
||||
if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
|
||||
return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t header is of incorrect size")
|
||||
}
|
||||
if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
|
||||
return errors.New("square/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
|
||||
}
|
||||
|
||||
// If certificate chain *and* thumbprints are set, verify correctness.
|
||||
@ -299,11 +317,11 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
sha256sum := sha256.Sum256(leaf.Raw)
|
||||
|
||||
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) {
|
||||
return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
|
||||
}
|
||||
|
||||
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) {
|
||||
return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,7 +350,7 @@ func (s *JSONWebKeySet) Key(kid string) []JSONWebKey {
|
||||
|
||||
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
|
||||
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
|
||||
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP",x":"%s"}`
|
||||
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP","x":"%s"}`
|
||||
|
||||
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
||||
coordLength := curveSize(curve)
|
||||
@ -342,7 +360,7 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
||||
}
|
||||
|
||||
if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
|
||||
return "", errors.New("square/go-jose: invalid elliptic key (too large)")
|
||||
return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ecThumbprintTemplate, crv,
|
||||
@ -359,7 +377,7 @@ func rsaThumbprintInput(n *big.Int, e int) (string, error) {
|
||||
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
|
||||
crv := "Ed25519"
|
||||
if len(ed) > 32 {
|
||||
return "", errors.New("square/go-jose: invalid elliptic key (too large)")
|
||||
return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
|
||||
}
|
||||
return fmt.Sprintf(edThumbprintTemplate, crv,
|
||||
newFixedSizeBuffer(ed, 32).base64()), nil
|
||||
@ -383,8 +401,10 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||
input, err = rsaThumbprintInput(key.N, key.E)
|
||||
case ed25519.PrivateKey:
|
||||
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
|
||||
case OpaqueSigner:
|
||||
return key.Public().Thumbprint(hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -392,7 +412,7 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||
}
|
||||
|
||||
h := hash.New()
|
||||
h.Write([]byte(input))
|
||||
_, _ = h.Write([]byte(input))
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
@ -406,7 +426,7 @@ func (k *JSONWebKey) IsPublic() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Public creates JSONWebKey with corresponding publik key if JWK represents asymmetric private key.
|
||||
// Public creates JSONWebKey with corresponding public key if JWK represents asymmetric private key.
|
||||
func (k *JSONWebKey) Public() JSONWebKey {
|
||||
if k.IsPublic() {
|
||||
return *k
|
||||
@ -463,7 +483,7 @@ func (k *JSONWebKey) Valid() bool {
|
||||
|
||||
func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
|
||||
if key.N == nil || key.E == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid RSA key, missing n/e values")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values")
|
||||
}
|
||||
|
||||
return &rsa.PublicKey{
|
||||
@ -498,29 +518,29 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
|
||||
case "P-521":
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
}
|
||||
|
||||
if key.X == nil || key.Y == nil {
|
||||
return nil, errors.New("square/go-jose: invalid EC key, missing x/y values")
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, missing x/y values")
|
||||
}
|
||||
|
||||
// The length of this octet string MUST be the full size of a coordinate for
|
||||
// the curve specified in the "crv" parameter.
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
|
||||
if curveSize(curve) != len(key.X.data) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for x")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x")
|
||||
}
|
||||
|
||||
if curveSize(curve) != len(key.Y.data) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for y")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y")
|
||||
}
|
||||
|
||||
x := key.X.bigInt()
|
||||
y := key.Y.bigInt()
|
||||
|
||||
if !curve.IsOnCurve(x, y) {
|
||||
return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
}
|
||||
|
||||
return &ecdsa.PublicKey{
|
||||
@ -532,7 +552,7 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
|
||||
|
||||
func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
|
||||
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC key (nil, or X/Y missing)")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (nil, or X/Y missing)")
|
||||
}
|
||||
|
||||
name, err := curveName(pub.Curve)
|
||||
@ -546,7 +566,7 @@ func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
|
||||
yBytes := pub.Y.Bytes()
|
||||
|
||||
if len(xBytes) > size || len(yBytes) > size {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC key (X/Y too large)")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (X/Y too large)")
|
||||
}
|
||||
|
||||
key := &rawJSONWebKey{
|
||||
@ -569,7 +589,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
privateKey := make([]byte, ed25519.PrivateKeySize)
|
||||
@ -581,7 +601,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
|
||||
|
||||
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
|
||||
if key.X == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid Ed key, missing x value")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value")
|
||||
}
|
||||
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||
copy(publicKey[0:32], key.X.bytes())
|
||||
@ -605,7 +625,7 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
rv := &rsa.PrivateKey{
|
||||
@ -675,34 +695,34 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
|
||||
case "P-521":
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
}
|
||||
|
||||
if key.X == nil || key.Y == nil || key.D == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key, missing x/y/d values")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values")
|
||||
}
|
||||
|
||||
// The length of this octet string MUST be the full size of a coordinate for
|
||||
// the curve specified in the "crv" parameter.
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
|
||||
if curveSize(curve) != len(key.X.data) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x")
|
||||
}
|
||||
|
||||
if curveSize(curve) != len(key.Y.data) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y")
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
|
||||
if dSize(curve) != len(key.D.data) {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for d")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d")
|
||||
}
|
||||
|
||||
x := key.X.bigInt()
|
||||
y := key.Y.bigInt()
|
||||
|
||||
if !curve.IsOnCurve(x, y) {
|
||||
return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
}
|
||||
|
||||
return &ecdsa.PrivateKey{
|
||||
@ -722,7 +742,7 @@ func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) {
|
||||
}
|
||||
|
||||
if ec.D == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid EC private key")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key")
|
||||
}
|
||||
|
||||
raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve))
|
||||
@ -740,7 +760,7 @@ func dSize(curve elliptic.Curve) int {
|
||||
bitLen := order.BitLen()
|
||||
size := bitLen / 8
|
||||
if bitLen%8 != 0 {
|
||||
size = size + 1
|
||||
size++
|
||||
}
|
||||
return size
|
||||
}
|
||||
@ -754,7 +774,50 @@ func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) {
|
||||
|
||||
func (key rawJSONWebKey) symmetricKey() ([]byte, error) {
|
||||
if key.K == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid OCT (symmetric) key, missing k value")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid OCT (symmetric) key, missing k value")
|
||||
}
|
||||
return key.K.bytes(), nil
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrJWKSKidNotFound is returned when a JWKS does not contain a JWK with a
|
||||
// key ID which matches one in the provided tokens headers.
|
||||
ErrJWKSKidNotFound = errors.New("go-jose/go-jose: JWK with matching kid not found in JWK Set")
|
||||
)
|
||||
|
||||
func tryJWKS(key interface{}, headers ...Header) (interface{}, error) {
|
||||
var jwks JSONWebKeySet
|
||||
|
||||
switch jwksType := key.(type) {
|
||||
case *JSONWebKeySet:
|
||||
jwks = *jwksType
|
||||
case JSONWebKeySet:
|
||||
jwks = jwksType
|
||||
default:
|
||||
// If the specified key is not a JWKS, return as is.
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// Determine the KID to search for from the headers.
|
||||
var kid string
|
||||
for _, header := range headers {
|
||||
if header.KeyID != "" {
|
||||
kid = header.KeyID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If no KID is specified in the headers, reject.
|
||||
if kid == "" {
|
||||
return nil, ErrJWKSKidNotFound
|
||||
}
|
||||
|
||||
// Find the JWK with the matching KID. If no JWK with the specified KID is
|
||||
// found, reject.
|
||||
keys := jwks.Key(kid)
|
||||
if len(keys) == 0 {
|
||||
return nil, ErrJWKSKidNotFound
|
||||
}
|
||||
|
||||
return keys[0].Key, nil
|
||||
}
|
103
vendor/gopkg.in/square/go-jose.v2/jws.go → vendor/github.com/go-jose/go-jose/v4/jws.go
generated
vendored
103
vendor/gopkg.in/square/go-jose.v2/jws.go → vendor/github.com/go-jose/go-jose/v4/jws.go
generated
vendored
@ -23,7 +23,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
|
||||
@ -75,22 +75,41 @@ type Signature struct {
|
||||
original *rawSignatureInfo
|
||||
}
|
||||
|
||||
// ParseSigned parses a signed message in compact or full serialization format.
|
||||
func ParseSigned(signature string) (*JSONWebSignature, error) {
|
||||
// ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7515#section-7
|
||||
func ParseSigned(
|
||||
signature string,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
signature = stripWhitespace(signature)
|
||||
if strings.HasPrefix(signature, "{") {
|
||||
return parseSignedFull(signature)
|
||||
return ParseSignedJSON(signature, signatureAlgorithms)
|
||||
}
|
||||
|
||||
return parseSignedCompact(signature, nil)
|
||||
return parseSignedCompact(signature, nil, signatureAlgorithms)
|
||||
}
|
||||
|
||||
// ParseSignedCompact parses a message in JWS Compact Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1
|
||||
func ParseSignedCompact(
|
||||
signature string,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
return parseSignedCompact(signature, nil, signatureAlgorithms)
|
||||
}
|
||||
|
||||
// ParseDetached parses a signed message in compact serialization format with detached payload.
|
||||
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) {
|
||||
func ParseDetached(
|
||||
signature string,
|
||||
payload []byte,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
if payload == nil {
|
||||
return nil, errors.New("square/go-jose: nil payload")
|
||||
return nil, errors.New("go-jose/go-jose: nil payload")
|
||||
}
|
||||
return parseSignedCompact(stripWhitespace(signature), payload)
|
||||
return parseSignedCompact(stripWhitespace(signature), payload, signatureAlgorithms)
|
||||
}
|
||||
|
||||
// Get a header value
|
||||
@ -137,21 +156,38 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
|
||||
return authData.Bytes(), nil
|
||||
}
|
||||
|
||||
// parseSignedFull parses a message in full format.
|
||||
func parseSignedFull(input string) (*JSONWebSignature, error) {
|
||||
// ParseSignedJSON parses a message in JWS JSON Serialization.
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.2
|
||||
func ParseSignedJSON(
|
||||
input string,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
var parsed rawJSONWebSignature
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parsed.sanitized()
|
||||
return parsed.sanitized(signatureAlgorithms)
|
||||
}
|
||||
|
||||
func containsSignatureAlgorithm(haystack []SignatureAlgorithm, needle SignatureAlgorithm) bool {
|
||||
for _, algorithm := range haystack {
|
||||
if algorithm == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// sanitized produces a cleaned-up JWS object from the raw JSON.
|
||||
func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgorithm) (*JSONWebSignature, error) {
|
||||
if len(signatureAlgorithms) == 0 {
|
||||
return nil, errors.New("go-jose/go-jose: no signature algorithms specified")
|
||||
}
|
||||
if parsed.Payload == nil {
|
||||
return nil, fmt.Errorf("square/go-jose: missing payload in JWS message")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
|
||||
}
|
||||
|
||||
obj := &JSONWebSignature{
|
||||
@ -198,6 +234,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alg := SignatureAlgorithm(signature.Header.Algorithm)
|
||||
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
|
||||
alg, signatureAlgorithms)
|
||||
}
|
||||
|
||||
if signature.header != nil {
|
||||
signature.Unprotected, err = signature.header.sanitized()
|
||||
if err != nil {
|
||||
@ -215,7 +257,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||
jwk := signature.Header.JSONWebKey
|
||||
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
|
||||
return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key")
|
||||
return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
|
||||
}
|
||||
|
||||
obj.Signatures = append(obj.Signatures, signature)
|
||||
@ -241,6 +283,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm)
|
||||
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
|
||||
alg, signatureAlgorithms)
|
||||
}
|
||||
|
||||
if obj.Signatures[i].header != nil {
|
||||
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
|
||||
if err != nil {
|
||||
@ -260,7 +308,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||
jwk := obj.Signatures[i].Header.JSONWebKey
|
||||
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
|
||||
return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key")
|
||||
return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
|
||||
}
|
||||
|
||||
// Copy value of sig
|
||||
@ -274,14 +322,18 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
}
|
||||
|
||||
// parseSignedCompact parses a message in compact format.
|
||||
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) {
|
||||
func parseSignedCompact(
|
||||
input string,
|
||||
payload []byte,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
parts := strings.Split(input, ".")
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
|
||||
}
|
||||
|
||||
if parts[1] != "" && payload != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: payload is not detached")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
|
||||
}
|
||||
|
||||
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||
@ -306,7 +358,7 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error)
|
||||
Protected: newBuffer(rawProtected),
|
||||
Signature: newBuffer(signature),
|
||||
}
|
||||
return raw.sanitized()
|
||||
return raw.sanitized(signatureAlgorithms)
|
||||
}
|
||||
|
||||
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
||||
@ -314,15 +366,18 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected))
|
||||
payload := ""
|
||||
signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)
|
||||
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
|
||||
|
||||
var payload []byte
|
||||
if !detached {
|
||||
payload = base64.RawURLEncoding.EncodeToString(obj.payload)
|
||||
payload = obj.payload
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
payload,
|
||||
obj.Signatures[0].Signature,
|
||||
), nil
|
||||
}
|
||||
|
||||
// CompactSerialize serializes an object using the compact serialization format.
|
@ -17,7 +17,7 @@
|
||||
package jose
|
||||
|
||||
// OpaqueSigner is an interface that supports signing payloads with opaque
|
||||
// private key(s). Private key operations preformed by implementors may, for
|
||||
// private key(s). Private key operations performed by implementers may, for
|
||||
// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
|
||||
// transparently to the user of this interface.
|
||||
type OpaqueSigner interface {
|
||||
@ -83,6 +83,9 @@ func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg Sig
|
||||
}
|
||||
|
||||
// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key.
|
||||
//
|
||||
// Note: this cannot currently be implemented outside this package because of its
|
||||
// unexported method.
|
||||
type OpaqueKeyEncrypter interface {
|
||||
// KeyID returns the kid
|
||||
KeyID() string
|
||||
@ -121,7 +124,7 @@ func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||
return oke.encrypter.encryptKey(cek, alg)
|
||||
}
|
||||
|
||||
//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||
// OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||
type OpaqueKeyDecrypter interface {
|
||||
DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
|
||||
}
|
@ -23,7 +23,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// KeyAlgorithm represents a key management algorithm.
|
||||
@ -45,32 +45,38 @@ var (
|
||||
// ErrCryptoFailure represents an error in cryptographic primitive. This
|
||||
// occurs when, for example, a message had an invalid authentication tag or
|
||||
// could not be decrypted.
|
||||
ErrCryptoFailure = errors.New("square/go-jose: error in cryptographic primitive")
|
||||
ErrCryptoFailure = errors.New("go-jose/go-jose: error in cryptographic primitive")
|
||||
|
||||
// ErrUnsupportedAlgorithm indicates that a selected algorithm is not
|
||||
// supported. This occurs when trying to instantiate an encrypter for an
|
||||
// algorithm that is not yet implemented.
|
||||
ErrUnsupportedAlgorithm = errors.New("square/go-jose: unknown/unsupported algorithm")
|
||||
ErrUnsupportedAlgorithm = errors.New("go-jose/go-jose: unknown/unsupported algorithm")
|
||||
|
||||
// ErrUnsupportedKeyType indicates that the given key type/format is not
|
||||
// supported. This occurs when trying to instantiate an encrypter and passing
|
||||
// it a key of an unrecognized type or with unsupported parameters, such as
|
||||
// an RSA private key with more than two primes.
|
||||
ErrUnsupportedKeyType = errors.New("square/go-jose: unsupported key type/format")
|
||||
ErrUnsupportedKeyType = errors.New("go-jose/go-jose: unsupported key type/format")
|
||||
|
||||
// ErrInvalidKeySize indicates that the given key is not the correct size
|
||||
// for the selected algorithm. This can occur, for example, when trying to
|
||||
// encrypt with AES-256 but passing only a 128-bit key as input.
|
||||
ErrInvalidKeySize = errors.New("square/go-jose: invalid key size for algorithm")
|
||||
ErrInvalidKeySize = errors.New("go-jose/go-jose: invalid key size for algorithm")
|
||||
|
||||
// ErrNotSupported serialization of object is not supported. This occurs when
|
||||
// trying to compact-serialize an object which can't be represented in
|
||||
// compact form.
|
||||
ErrNotSupported = errors.New("square/go-jose: compact serialization not supported for object")
|
||||
ErrNotSupported = errors.New("go-jose/go-jose: compact serialization not supported for object")
|
||||
|
||||
// ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
|
||||
// nonce header parameter was included in an unprotected header object.
|
||||
ErrUnprotectedNonce = errors.New("square/go-jose: Nonce parameter included in unprotected header")
|
||||
ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header")
|
||||
|
||||
// ErrMissingX5cHeader indicates that the JWT header is missing x5c headers.
|
||||
ErrMissingX5cHeader = errors.New("go-jose/go-jose: no x5c header present in message")
|
||||
|
||||
// ErrUnsupportedEllipticCurve indicates unsupported or unknown elliptic curve has been found.
|
||||
ErrUnsupportedEllipticCurve = errors.New("go-jose/go-jose: unsupported/unknown elliptic curve")
|
||||
)
|
||||
|
||||
// Key management algorithms
|
||||
@ -133,8 +139,8 @@ const (
|
||||
type HeaderKey string
|
||||
|
||||
const (
|
||||
HeaderType HeaderKey = "typ" // string
|
||||
HeaderContentType = "cty" // string
|
||||
HeaderType = "typ" // string
|
||||
HeaderContentType = "cty" // string
|
||||
|
||||
// These are set by go-jose and shouldn't need to be set by consumers of the
|
||||
// library.
|
||||
@ -183,8 +189,13 @@ type Header struct {
|
||||
// Unverified certificate chain parsed from x5c header.
|
||||
certificates []*x509.Certificate
|
||||
|
||||
// Any headers not recognised above get unmarshaled
|
||||
// from JSON in a generic manner and placed in this map.
|
||||
// At parse time, each header parameter with a name other than "kid",
|
||||
// "jwk", "alg", "nonce", or "x5c" will have its value passed to
|
||||
// [json.Unmarshal] to unmarshal it into an interface value.
|
||||
// The resulting value will be stored in this map, with the header
|
||||
// parameter name as the key.
|
||||
//
|
||||
// [json.Unmarshal]: https://pkg.go.dev/encoding/json#Unmarshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
@ -194,7 +205,7 @@ type Header struct {
|
||||
// not be validated with the given verify options.
|
||||
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
|
||||
if len(h.certificates) == 0 {
|
||||
return nil, errors.New("square/go-jose: no x5c header present in message")
|
||||
return nil, ErrMissingX5cHeader
|
||||
}
|
||||
|
||||
leaf := h.certificates[0]
|
||||
@ -295,12 +306,12 @@ func (parsed rawHeader) getAPV() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerAPV)
|
||||
}
|
||||
|
||||
// getIV extracts parsed "iv" frpom the raw JSON.
|
||||
// getIV extracts parsed "iv" from the raw JSON.
|
||||
func (parsed rawHeader) getIV() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerIV)
|
||||
}
|
||||
|
||||
// getTag extracts parsed "tag" frpom the raw JSON.
|
||||
// getTag extracts parsed "tag" from the raw JSON.
|
||||
func (parsed rawHeader) getTag() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerTag)
|
||||
}
|
||||
@ -452,8 +463,8 @@ func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (dst rawHeader) isSet(k HeaderKey) bool {
|
||||
dvr := dst[k]
|
||||
func (parsed rawHeader) isSet(k HeaderKey) bool {
|
||||
dvr := parsed[k]
|
||||
if dvr == nil {
|
||||
return false
|
||||
}
|
||||
@ -472,17 +483,17 @@ func (dst rawHeader) isSet(k HeaderKey) bool {
|
||||
}
|
||||
|
||||
// Merge headers from src into dst, giving precedence to headers from l.
|
||||
func (dst rawHeader) merge(src *rawHeader) {
|
||||
func (parsed rawHeader) merge(src *rawHeader) {
|
||||
if src == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range *src {
|
||||
if dst.isSet(k) {
|
||||
if parsed.isSet(k) {
|
||||
continue
|
||||
}
|
||||
|
||||
dst[k] = v
|
||||
parsed[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,7 +507,7 @@ func curveName(crv elliptic.Curve) (string, error) {
|
||||
case elliptic.P521():
|
||||
return "P-521", nil
|
||||
default:
|
||||
return "", fmt.Errorf("square/go-jose: unsupported/unknown elliptic curve")
|
||||
return "", ErrUnsupportedEllipticCurve
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,13 @@ package jose
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// NonceSource represents a source of random nonces to go into JWS objects
|
||||
@ -41,6 +40,20 @@ type Signer interface {
|
||||
}
|
||||
|
||||
// SigningKey represents an algorithm/key used to sign a message.
|
||||
//
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that satisfies the OpaqueSigner interface
|
||||
//
|
||||
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
|
||||
// - HS256: 32 bytes
|
||||
// - HS384: 48 bytes
|
||||
// - HS512: 64 bytes
|
||||
type SigningKey struct {
|
||||
Algorithm SignatureAlgorithm
|
||||
Key interface{}
|
||||
@ -53,12 +66,22 @@ type SignerOptions struct {
|
||||
|
||||
// Optional map of additional keys to be inserted into the protected header
|
||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||
// additional values here. All values must be JSON-serializable.
|
||||
// additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary. It returns itself and so can be used in a fluent style.
|
||||
// if necessary, and returns the updated SignerOptions.
|
||||
//
|
||||
// The v argument will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
||||
if so.ExtraHeaders == nil {
|
||||
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
@ -174,11 +197,11 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||
return newVerifier(verificationKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newVerifier(verificationKey.Key)
|
||||
case OpaqueVerifier:
|
||||
return &opaqueVerifier{verifier: verificationKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if ov, ok := verificationKey.(OpaqueVerifier); ok {
|
||||
return &opaqueVerifier{verifier: ov}, nil
|
||||
}
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
||||
@ -205,11 +228,11 @@ func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipient
|
||||
return newJWKSigner(alg, signingKey)
|
||||
case *JSONWebKey:
|
||||
return newJWKSigner(alg, *signingKey)
|
||||
case OpaqueSigner:
|
||||
return newOpaqueSigner(alg, signingKey)
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
if signer, ok := signingKey.(OpaqueSigner); ok {
|
||||
return newOpaqueSigner(alg, signer)
|
||||
}
|
||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
||||
@ -227,7 +250,7 @@ func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigIn
|
||||
|
||||
// This should be impossible, but let's check anyway.
|
||||
if !recipient.publicKey().IsPublic() {
|
||||
return recipientSigInfo{}, errors.New("square/go-jose: public key was unexpectedly not public")
|
||||
return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public")
|
||||
}
|
||||
}
|
||||
return recipient, nil
|
||||
@ -251,7 +274,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
// result of the JOSE spec. We've decided that this library will only include one or
|
||||
// the other to avoid this confusion.
|
||||
//
|
||||
// See https://github.com/square/go-jose/issues/157 for more context.
|
||||
// See https://github.com/go-jose/go-jose/issues/157 for more context.
|
||||
if ctx.embedJWK {
|
||||
protected[headerJWK] = recipient.publicKey()
|
||||
} else {
|
||||
@ -265,7 +288,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
if ctx.nonceSource != nil {
|
||||
nonce, err := ctx.nonceSource.Nonce()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: Error generating nonce: %v", err)
|
||||
}
|
||||
protected[headerNonce] = nonce
|
||||
}
|
||||
@ -279,7 +302,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
|
||||
if b64, ok := protected[headerB64]; ok {
|
||||
if needsBase64, ok = b64.(bool); !ok {
|
||||
return nil, errors.New("square/go-jose: Invalid b64 header parameter")
|
||||
return nil, errors.New("go-jose/go-jose: Invalid b64 header parameter")
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +326,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
for k, v := range protected {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: Error marshalling item %#v: %v", k, err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: Error marshalling item %#v: %v", k, err)
|
||||
}
|
||||
(*signatureInfo.protected)[k] = makeRawMessage(b)
|
||||
}
|
||||
@ -322,12 +345,28 @@ func (ctx *genericSigner) Options() SignerOptions {
|
||||
}
|
||||
|
||||
// Verify validates the signature on the object and returns the payload.
|
||||
// This function does not support multi-signature, if you desire multi-sig
|
||||
// This function does not support multi-signature. If you desire multi-signature
|
||||
// verification use VerifyMulti instead.
|
||||
//
|
||||
// Be careful when verifying signatures based on embedded JWKs inside the
|
||||
// payload header. You cannot assume that the key received in a payload is
|
||||
// trusted.
|
||||
//
|
||||
// The verificationKey argument must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - *JSONWebKeySet
|
||||
// - JSONWebKeySet
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that implements the OpaqueVerifier interface.
|
||||
//
|
||||
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
|
||||
// - HS256: 32 bytes
|
||||
// - HS384: 48 bytes
|
||||
// - HS512: 64 bytes
|
||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||
err := obj.DetachedVerify(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
@ -347,14 +386,21 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
||||
// most cases, you will probably want to use Verify instead. DetachedVerify
|
||||
// is only useful if you have a payload and signature that are separated from
|
||||
// each other.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||
verifier, err := newVerifier(verificationKey)
|
||||
key, err := tryJWKS(verificationKey, obj.headers()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(obj.Signatures) > 1 {
|
||||
return errors.New("square/go-jose: too many signatures in payload; expecting only one")
|
||||
return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
|
||||
}
|
||||
|
||||
signature := obj.Signatures[0]
|
||||
@ -388,6 +434,9 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
|
||||
// returns the index of the signature that was verified, along with the signature
|
||||
// object and the payload. We return the signature and index to guarantee that
|
||||
// callers are getting the verified value.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
@ -405,8 +454,15 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
|
||||
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
||||
// separated from each other, and the signature can have multiple signers at the
|
||||
// same time.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||
verifier, err := newVerifier(verificationKey)
|
||||
key, err := tryJWKS(verificationKey, obj.headers()...)
|
||||
if err != nil {
|
||||
return -1, Signature{}, err
|
||||
}
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
return -1, Signature{}, err
|
||||
}
|
||||
@ -439,3 +495,11 @@ outer:
|
||||
|
||||
return -1, Signature{}, ErrCryptoFailure
|
||||
}
|
||||
|
||||
func (obj JSONWebSignature) headers() []Header {
|
||||
headers := make([]Header, len(obj.Signatures))
|
||||
for i, sig := range obj.Signatures {
|
||||
headers[i] = sig.Header
|
||||
}
|
||||
return headers
|
||||
}
|
@ -31,20 +31,26 @@ import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"gopkg.in/square/go-jose.v2/cipher"
|
||||
|
||||
josecipher "github.com/go-jose/go-jose/v4/cipher"
|
||||
)
|
||||
|
||||
// Random reader (stubbed out in tests)
|
||||
// RandReader is a cryptographically secure random number generator (stubbed out in tests).
|
||||
var RandReader = rand.Reader
|
||||
|
||||
const (
|
||||
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||
// https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||
// - https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||
//
|
||||
// NIST recommends a minimum of 10,000:
|
||||
// https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
// 1Password uses 100,000:
|
||||
// https://support.1password.com/pbkdf2/
|
||||
defaultP2C = 100000
|
||||
// - https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
//
|
||||
// 1Password increased in 2023 from 100,000 to 650,000:
|
||||
// - https://support.1password.com/pbkdf2/
|
||||
//
|
||||
// OWASP recommended 600,000 in Dec 2022:
|
||||
// - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
|
||||
defaultP2C = 600000
|
||||
// Default salt size: 128 bits
|
||||
defaultP2SSize = 16
|
||||
)
|
||||
@ -278,8 +284,14 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||
}
|
||||
|
||||
header := &rawHeader{}
|
||||
header.set(headerIV, newBuffer(parts.iv))
|
||||
header.set(headerTag, newBuffer(parts.tag))
|
||||
|
||||
if err = header.set(headerIV, newBuffer(parts.iv)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
if err = header.set(headerTag, newBuffer(parts.tag)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
header: header,
|
||||
@ -332,8 +344,14 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
|
||||
}
|
||||
|
||||
header := &rawHeader{}
|
||||
header.set(headerP2C, ctx.p2c)
|
||||
header.set(headerP2S, newBuffer(ctx.p2s))
|
||||
|
||||
if err = header.set(headerP2C, ctx.p2c); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
if err = header.set(headerP2S, newBuffer(ctx.p2s)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
encryptedKey: jek,
|
||||
@ -356,11 +374,11 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||
|
||||
iv, err := headers.getIV()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid IV: %v", err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid IV: %v", err)
|
||||
}
|
||||
tag, err := headers.getTag()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid tag: %v", err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid tag: %v", err)
|
||||
}
|
||||
|
||||
parts := &aeadParts{
|
||||
@ -389,18 +407,23 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||
p2s, err := headers.getP2S()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid P2S: %v", err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err)
|
||||
}
|
||||
if p2s == nil || len(p2s.data) == 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid P2S: must be present")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present")
|
||||
}
|
||||
|
||||
p2c, err := headers.getP2C()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid P2C: %v", err)
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: %v", err)
|
||||
}
|
||||
if p2c <= 0 {
|
||||
return nil, fmt.Errorf("square/go-jose: invalid P2C: must be a positive integer")
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
|
||||
}
|
||||
if p2c > 1000000 {
|
||||
// An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid
|
||||
// DoS attacks.
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high")
|
||||
}
|
||||
|
||||
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||
@ -431,7 +454,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
|
||||
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
mac, err := ctx.hmac(payload, alg)
|
||||
if err != nil {
|
||||
return Signature{}, errors.New("square/go-jose: failed to compute hmac")
|
||||
return Signature{}, err
|
||||
}
|
||||
|
||||
return Signature{
|
||||
@ -444,16 +467,16 @@ func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Sig
|
||||
func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error {
|
||||
expected, err := ctx.hmac(payload, alg)
|
||||
if err != nil {
|
||||
return errors.New("square/go-jose: failed to compute hmac")
|
||||
return errors.New("go-jose/go-jose: failed to compute hmac")
|
||||
}
|
||||
|
||||
if len(mac) != len(expected) {
|
||||
return errors.New("square/go-jose: invalid hmac")
|
||||
return errors.New("go-jose/go-jose: invalid hmac")
|
||||
}
|
||||
|
||||
match := subtle.ConstantTimeCompare(mac, expected)
|
||||
if match != 1 {
|
||||
return errors.New("square/go-jose: invalid hmac")
|
||||
return errors.New("go-jose/go-jose: invalid hmac")
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -463,12 +486,24 @@ func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureA
|
||||
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
|
||||
var hash func() hash.Hash
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/rfc7518#section-3.2
|
||||
// A key of the same size as the hash output (for instance, 256 bits for
|
||||
// "HS256") or larger MUST be used
|
||||
switch alg {
|
||||
case HS256:
|
||||
if len(ctx.key)*8 < 256 {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
hash = sha256.New
|
||||
case HS384:
|
||||
if len(ctx.key)*8 < 384 {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
hash = sha512.New384
|
||||
case HS512:
|
||||
if len(ctx.key)*8 < 512 {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
hash = sha512.New
|
||||
default:
|
||||
return nil, ErrUnsupportedAlgorithm
|
32
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
Normal file
32
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
codecov:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 70%
|
||||
threshold: 2%
|
||||
patch: off
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "header,diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
|
||||
ignore:
|
||||
- internal/encoder/vm_color
|
||||
- internal/encoder/vm_color_indent
|
2
vendor/github.com/goccy/go-json/.gitignore
generated
vendored
Normal file
2
vendor/github.com/goccy/go-json/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
cover.html
|
||||
cover.out
|
86
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
Normal file
86
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
run:
|
||||
skip-files:
|
||||
- encode_optype.go
|
||||
- ".*_test\\.go$"
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- shadow
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- dogsled
|
||||
- dupl
|
||||
- exhaustive
|
||||
- exhaustivestruct
|
||||
- errorlint
|
||||
- forbidigo
|
||||
- funlen
|
||||
- gci
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- goerr113
|
||||
- gofumpt
|
||||
- gomnd
|
||||
- gosec
|
||||
- ifshort
|
||||
- lll
|
||||
- makezero
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- paralleltest
|
||||
- testpackage
|
||||
- thelper
|
||||
- wrapcheck
|
||||
- interfacer
|
||||
- lll
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- testpackage
|
||||
- wsl
|
||||
- varnamelen
|
||||
- nilnil
|
||||
- ireturn
|
||||
- govet
|
||||
- forcetypeassert
|
||||
- cyclop
|
||||
- containedctx
|
||||
- revive
|
||||
- nosnakecase
|
||||
- exhaustruct
|
||||
- depguard
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# not needed
|
||||
- path: /*.go
|
||||
text: "ST1003: should not use underscores in package names"
|
||||
linters:
|
||||
- stylecheck
|
||||
- path: /*.go
|
||||
text: "don't use an underscore in package name"
|
||||
linters:
|
||||
- golint
|
||||
- path: rtype.go
|
||||
linters:
|
||||
- golint
|
||||
- stylecheck
|
||||
- path: error.go
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-issues-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
425
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
Normal file
425
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,425 @@
|
||||
# v0.10.2 - 2023/03/20
|
||||
|
||||
### New features
|
||||
|
||||
* Support DebugDOT option for debugging encoder ( #440 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix combination of embedding structure and omitempty option ( #442 )
|
||||
|
||||
# v0.10.1 - 2023/03/13
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix checkptr error for array decoder ( #415 )
|
||||
* Fix added buffer size check when decoding key ( #430 )
|
||||
* Fix handling of anonymous fields other than struct ( #431 )
|
||||
* Fix to not optimize when lower conversion can't handle byte-by-byte ( #432 )
|
||||
* Fix a problem that MarshalIndent does not work when UnorderedMap is specified ( #435 )
|
||||
* Fix mapDecoder.DecodeStream() for empty objects containing whitespace ( #425 )
|
||||
* Fix an issue that could not set the correct NextField for fields in the embedded structure ( #438 )
|
||||
|
||||
# v0.10.0 - 2022/11/29
|
||||
|
||||
### New features
|
||||
|
||||
* Support JSON Path ( #250 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix marshaler for map's key ( #409 )
|
||||
|
||||
# v0.9.11 - 2022/08/18
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix unexpected behavior when buffer ends with backslash ( #383 )
|
||||
* Fix stream decoding of escaped character ( #387 )
|
||||
|
||||
# v0.9.10 - 2022/07/15
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix boundary exception of type caching ( #382 )
|
||||
|
||||
# v0.9.9 - 2022/07/15
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix encoding of directed interface with typed nil ( #377 )
|
||||
* Fix embedded primitive type encoding using alias ( #378 )
|
||||
* Fix slice/array type encoding with types implementing MarshalJSON ( #379 )
|
||||
* Fix unicode decoding when the expected buffer state is not met after reading ( #380 )
|
||||
|
||||
# v0.9.8 - 2022/06/30
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix decoding of surrogate-pair ( #365 )
|
||||
* Fix handling of embedded primitive type ( #366 )
|
||||
* Add validation of escape sequence for decoder ( #367 )
|
||||
* Fix stream tokenizing respecting UseNumber ( #369 )
|
||||
* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 )
|
||||
|
||||
### Improve performance
|
||||
|
||||
* Improve performance of linkRecursiveCode ( #368 )
|
||||
|
||||
# v0.9.7 - 2022/04/22
|
||||
|
||||
### Fix bugs
|
||||
|
||||
#### Encoder
|
||||
|
||||
* Add filtering process for encoding on slow path ( #355 )
|
||||
* Fix encoding of interface{} with pointer type ( #363 )
|
||||
|
||||
#### Decoder
|
||||
|
||||
* Fix map key decoder that implements UnmarshalJSON ( #353 )
|
||||
* Fix decoding of []uint8 type ( #361 )
|
||||
|
||||
### New features
|
||||
|
||||
* Add DebugWith option for encoder ( #356 )
|
||||
|
||||
# v0.9.6 - 2022/03/22
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Correct the handling of the minimum value of int type for decoder ( #344 )
|
||||
* Fix bugs of stream decoder's bufferSize ( #349 )
|
||||
* Add a guard to use typeptr more safely ( #351 )
|
||||
|
||||
### Improve decoder performance
|
||||
|
||||
* Improve escapeString's performance ( #345 )
|
||||
|
||||
### Others
|
||||
|
||||
* Update go version for CI ( #347 )
|
||||
|
||||
# v0.9.5 - 2022/03/04
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix panic when decoding time.Time with context ( #328 )
|
||||
* Fix reading the next character in buffer to nul consideration ( #338 )
|
||||
* Fix incorrect handling on skipValue ( #341 )
|
||||
|
||||
### Improve decoder performance
|
||||
|
||||
* Improve performance when a payload contains escape sequence ( #334 )
|
||||
|
||||
# v0.9.4 - 2022/01/21
|
||||
|
||||
* Fix IsNilForMarshaler for string type with omitempty ( #323 )
|
||||
* Fix the case where the embedded field is at the end ( #326 )
|
||||
|
||||
# v0.9.3 - 2022/01/14
|
||||
|
||||
* Fix logic of removing struct field for decoder ( #322 )
|
||||
|
||||
# v0.9.2 - 2022/01/14
|
||||
|
||||
* Add invalid decoder to delay type error judgment at decode ( #321 )
|
||||
|
||||
# v0.9.1 - 2022/01/11
|
||||
|
||||
* Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 )
|
||||
|
||||
# v0.9.0 - 2022/01/05
|
||||
|
||||
### New feature
|
||||
|
||||
* Supports dynamic filtering of struct fields ( #314 )
|
||||
|
||||
### Improve encoding performance
|
||||
|
||||
* Improve map encoding performance ( #310 )
|
||||
* Optimize encoding path for escaped string ( #311 )
|
||||
* Add encoding option for performance ( #312 )
|
||||
|
||||
### Fix bugs
|
||||
|
||||
* Fix panic at encoding map value on 1.18 ( #310 )
|
||||
* Fix MarshalIndent for interface type ( #317 )
|
||||
|
||||
# v0.8.1 - 2021/12/05
|
||||
|
||||
* Fix operation conversion from PtrHead to Head in Recursive type ( #305 )
|
||||
|
||||
# v0.8.0 - 2021/12/02
|
||||
|
||||
* Fix embedded field conflict behavior ( #300 )
|
||||
* Refactor compiler for encoder ( #301 #302 )
|
||||
|
||||
# v0.7.10 - 2021/10/16
|
||||
|
||||
* Fix conversion from pointer to uint64 ( #294 )
|
||||
|
||||
# v0.7.9 - 2021/09/28
|
||||
|
||||
* Fix encoding of nil value about interface type that has method ( #291 )
|
||||
|
||||
# v0.7.8 - 2021/09/01
|
||||
|
||||
* Fix mapassign_faststr for indirect struct type ( #283 )
|
||||
* Fix encoding of not empty interface type ( #284 )
|
||||
* Fix encoding of empty struct interface type ( #286 )
|
||||
|
||||
# v0.7.7 - 2021/08/25
|
||||
|
||||
* Fix invalid utf8 on stream decoder ( #279 )
|
||||
* Fix buffer length bug on string stream decoder ( #280 )
|
||||
|
||||
Thank you @orisano !!
|
||||
|
||||
# v0.7.6 - 2021/08/13
|
||||
|
||||
* Fix nil slice assignment ( #276 )
|
||||
* Improve error message ( #277 )
|
||||
|
||||
# v0.7.5 - 2021/08/12
|
||||
|
||||
* Fix encoding of embedded struct with tags ( #265 )
|
||||
* Fix encoding of embedded struct that isn't first field ( #272 )
|
||||
* Fix decoding of binary type with escaped char ( #273 )
|
||||
|
||||
# v0.7.4 - 2021/07/06
|
||||
|
||||
* Fix encoding of indirect layout structure ( #264 )
|
||||
|
||||
# v0.7.3 - 2021/06/29
|
||||
|
||||
* Fix encoding of pointer type in empty interface ( #262 )
|
||||
|
||||
# v0.7.2 - 2021/06/26
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Add decoder for func type to fix decoding of nil function value ( #257 )
|
||||
* Fix stream decoding of []byte type ( #258 )
|
||||
|
||||
### Performance
|
||||
|
||||
* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 )
|
||||
* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 )
|
||||
|
||||
### Benchmark
|
||||
|
||||
* Add bytedance/sonic as benchmark target ( #254 )
|
||||
|
||||
# v0.7.1 - 2021/06/18
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix error when unmarshal empty array ( #253 )
|
||||
|
||||
# v0.7.0 - 2021/06/12
|
||||
|
||||
### Support context for MarshalJSON and UnmarshalJSON ( #248 )
|
||||
|
||||
* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error)
|
||||
* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error
|
||||
* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error
|
||||
* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error
|
||||
|
||||
```go
|
||||
type MarshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
type UnmarshalerContext interface {
|
||||
UnmarshalJSON(context.Context, []byte) error
|
||||
}
|
||||
```
|
||||
|
||||
### Add DecodeFieldPriorityFirstWin option ( #242 )
|
||||
|
||||
In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix indent number contains recursive type ( #249 )
|
||||
* Fix encoding of using empty interface as map key ( #244 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding fields containing escaped characters ( #237 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* Move some tests to subdirectory ( #243 )
|
||||
* Refactor package layout for decoder ( #238 )
|
||||
|
||||
# v0.6.1 - 2021/06/02
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix value of totalLength for encoding ( #236 )
|
||||
|
||||
# v0.6.0 - 2021/06/01
|
||||
|
||||
### Support Colorize option for encoding (#233)
|
||||
|
||||
```go
|
||||
b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme))
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
fmt.Println(string(b)) // print colored json
|
||||
```
|
||||
|
||||
### Refactor
|
||||
|
||||
* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 )
|
||||
* Refactor encode option ( #231 )
|
||||
* Refactor escape string ( #232 )
|
||||
|
||||
# v0.5.1 - 2021/5/20
|
||||
|
||||
### Optimization
|
||||
|
||||
* Add type addrShift to enable bigger encoder/decoder cache ( #213 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Keep original reference of slice element ( #229 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* Refactor Debug mode for encoding ( #226 )
|
||||
* Generate VM sources for encoding ( #227 )
|
||||
* Refactor validator for null/true/false for decoding ( #221 )
|
||||
|
||||
# v0.5.0 - 2021/5/9
|
||||
|
||||
### Supports using omitempty and string tags at the same time ( #216 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix stream decoder for unicode char ( #215 )
|
||||
* Fix decoding of slice element ( #219 )
|
||||
* Fix calculating of buffer length for stream decoder ( #220 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* replace skipWhiteSpace goto by loop ( #212 )
|
||||
|
||||
# v0.4.14 - 2021/5/4
|
||||
|
||||
### Benchmark
|
||||
|
||||
* Add valyala/fastjson to benchmark ( #193 )
|
||||
* Add benchmark task for CI ( #211 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding of slice with unmarshal json type ( #198 )
|
||||
* Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 )
|
||||
* Fix decoding of null value to []byte by json.Unmarshal ( #206 )
|
||||
* Fix decoding of backslash char at the end of string ( #207 )
|
||||
* Fix stream decoder for null/true/false value ( #208 )
|
||||
* Fix stream decoder for slow reader ( #211 )
|
||||
|
||||
### Performance
|
||||
|
||||
* If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 )
|
||||
|
||||
# v0.4.13 - 2021/4/20
|
||||
|
||||
### Fix json.Compact and json.Indent
|
||||
|
||||
* Support validation the input buffer for json.Compact and json.Indent ( #189 )
|
||||
* Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 )
|
||||
|
||||
# v0.4.12 - 2021/4/15
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix unnecessary indent for empty slice type ( #181 )
|
||||
* Fix encoding of omitempty feature for the slice or interface type ( #183 )
|
||||
* Fix encoding custom types zero values with omitempty when marshaller exists ( #187 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoder for invalid top level value ( #184 )
|
||||
* Fix decoder for invalid number value ( #185 )
|
||||
|
||||
# v0.4.11 - 2021/4/3
|
||||
|
||||
* Improve decoder performance for interface type
|
||||
|
||||
# v0.4.10 - 2021/4/2
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fixed a bug when encoding slice and map containing recursive structures
|
||||
* Fixed a logic to determine if indirect reference
|
||||
|
||||
# v0.4.9 - 2021/3/29
|
||||
|
||||
### Add debug mode
|
||||
|
||||
If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console.
|
||||
|
||||
### Support a new feature to compatible with encoding/json
|
||||
|
||||
- invalid UTF-8 is coerced to valid UTF-8 ( without performance down )
|
||||
|
||||
### Fix encoder
|
||||
|
||||
- Fixed handling of MarshalJSON of function type
|
||||
|
||||
### Fix decoding of slice of pointer type
|
||||
|
||||
If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`.
|
||||
|
||||
# v0.4.8 - 2021/3/21
|
||||
|
||||
### Reduce memory usage at compile time
|
||||
|
||||
* go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB.
|
||||
|
||||
### Fix any encoder's bug
|
||||
|
||||
* Add many test cases for encoder
|
||||
* Fix composite type ( slice/array/map )
|
||||
* Fix pointer types
|
||||
* Fix encoding of MarshalJSON or MarshalText or json.Number type
|
||||
|
||||
### Refactor encoder
|
||||
|
||||
* Change package layout for reducing memory usage at compile
|
||||
* Remove anonymous and only operation
|
||||
* Remove root property from encodeCompileContext and opcode
|
||||
|
||||
### Fix CI
|
||||
|
||||
* Add Go 1.16
|
||||
* Remove Go 1.13
|
||||
* Fix `make cover` task
|
||||
|
||||
### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias
|
||||
|
||||
# v0.4.7 - 2021/02/22
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding of deep recursive structure
|
||||
* Fix decoding of embedded unexported pointer field
|
||||
* Fix invalid test case
|
||||
* Fix decoding of invalid value
|
||||
* Fix decoding of prefilled value
|
||||
* Fix not being able to return UnmarshalTypeError when it should be returned
|
||||
* Fix decoding of null value
|
||||
* Fix decoding of type of null string
|
||||
* Use pre allocated pointer if exists it at decoding
|
||||
|
||||
### Reduce memory usage at compile
|
||||
|
||||
* Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile
|
||||
|
||||
### Remove unnecessary optype
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user