Browse Source

[Vendor] update certmagic (#15590)

* update github.com/caddyserver/certmagic v0.12.0 -> v0.13.0

* migrate
pull/15596/head
6543 3 weeks ago
committed by GitHub
parent
commit
8ea1d32bea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
177 changed files with 4720 additions and 1979 deletions
  1. +1
    -1
      cmd/web_letsencrypt.go
  2. +6
    -8
      go.mod
  3. +17
    -15
      go.sum
  4. +3
    -3
      vendor/github.com/caddyserver/certmagic/README.md
  5. +85
    -54
      vendor/github.com/caddyserver/certmagic/account.go
  6. +115
    -78
      vendor/github.com/caddyserver/certmagic/acmeclient.go
  7. +135
    -19
      vendor/github.com/caddyserver/certmagic/acmemanager.go
  8. +39
    -31
      vendor/github.com/caddyserver/certmagic/certificates.go
  9. +15
    -9
      vendor/github.com/caddyserver/certmagic/certmagic.go
  10. +265
    -126
      vendor/github.com/caddyserver/certmagic/config.go
  11. +84
    -50
      vendor/github.com/caddyserver/certmagic/crypto.go
  12. +15
    -4
      vendor/github.com/caddyserver/certmagic/filestorage.go
  13. +3
    -2
      vendor/github.com/caddyserver/certmagic/go.mod
  14. +4
    -8
      vendor/github.com/caddyserver/certmagic/go.sum
  15. +191
    -131
      vendor/github.com/caddyserver/certmagic/handshake.go
  16. +20
    -29
      vendor/github.com/caddyserver/certmagic/httphandler.go
  17. +5
    -2
      vendor/github.com/caddyserver/certmagic/maintain.go
  18. +22
    -5
      vendor/github.com/caddyserver/certmagic/ocsp.go
  19. +94
    -33
      vendor/github.com/caddyserver/certmagic/solvers.go
  20. +11
    -5
      vendor/github.com/caddyserver/certmagic/storage.go
  21. +1
    -1
      vendor/github.com/miekg/dns/Makefile.release
  22. +1
    -1
      vendor/github.com/miekg/dns/client.go
  23. +1
    -4
      vendor/github.com/miekg/dns/defaults.go
  24. +2
    -3
      vendor/github.com/miekg/dns/dnssec.go
  25. +1
    -2
      vendor/github.com/miekg/dns/dnssec_keygen.go
  26. +1
    -2
      vendor/github.com/miekg/dns/dnssec_keyscan.go
  27. +1
    -2
      vendor/github.com/miekg/dns/dnssec_privkey.go
  28. +1
    -1
      vendor/github.com/miekg/dns/edns.go
  29. +4
    -6
      vendor/github.com/miekg/dns/go.mod
  30. +9
    -38
      vendor/github.com/miekg/dns/go.sum
  31. +1
    -1
      vendor/github.com/miekg/dns/labels.go
  32. +1
    -1
      vendor/github.com/miekg/dns/msg.go
  33. +1
    -1
      vendor/github.com/miekg/dns/privaterr.go
  34. +2
    -2
      vendor/github.com/miekg/dns/scan.go
  35. +39
    -7
      vendor/github.com/miekg/dns/scan_rr.go
  36. +2
    -2
      vendor/github.com/miekg/dns/sig0.go
  37. +2
    -2
      vendor/github.com/miekg/dns/svcb.go
  38. +30
    -1
      vendor/github.com/miekg/dns/types.go
  39. +1
    -1
      vendor/github.com/miekg/dns/version.go
  40. +21
    -0
      vendor/github.com/miekg/dns/zduplicate.go
  41. +52
    -0
      vendor/github.com/miekg/dns/zmsg.go
  42. +14
    -0
      vendor/github.com/miekg/dns/ztypes.go
  43. +9
    -9
      vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s
  44. +11
    -12
      vendor/golang.org/x/crypto/scrypt/scrypt.go
  45. +5
    -2
      vendor/golang.org/x/net/internal/socket/sys_const_unix.go
  46. +0
    -18
      vendor/golang.org/x/net/internal/socket/sys_const_zos.go
  47. +3
    -3
      vendor/golang.org/x/net/internal/socket/sys_posix.go
  48. +3
    -0
      vendor/golang.org/x/net/internal/socket/sys_stub.go
  49. +1
    -18
      vendor/golang.org/x/net/internal/socket/sys_windows.go
  50. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go
  51. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go
  52. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go
  53. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go
  54. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go
  55. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go
  56. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go
  57. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go
  58. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go
  59. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm64.go
  60. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_386.go
  61. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go
  62. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go
  63. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go
  64. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go
  65. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go
  66. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go
  67. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go
  68. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go
  69. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go
  70. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go
  71. +0
    -18
      vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go
  72. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go
  73. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go
  74. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go
  75. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go
  76. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go
  77. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go
  78. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go
  79. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm64.go
  80. +0
    -20
      vendor/golang.org/x/net/internal/socket/zsys_openbsd_mips64.go
  81. +0
    -19
      vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go
  82. +1
    -5
      vendor/golang.org/x/net/internal/socket/zsys_zos_s390x.go
  83. +4
    -2
      vendor/golang.org/x/net/ipv4/control_bsd.go
  84. +3
    -1
      vendor/golang.org/x/net/ipv4/control_unix.go
  85. +3
    -0
      vendor/golang.org/x/net/ipv4/sys_aix.go
  86. +2
    -0
      vendor/golang.org/x/net/ipv4/sys_bsd.go
  87. +2
    -0
      vendor/golang.org/x/net/ipv4/sys_darwin.go
  88. +2
    -0
      vendor/golang.org/x/net/ipv4/sys_dragonfly.go
  89. +2
    -0
      vendor/golang.org/x/net/ipv4/sys_freebsd.go
  90. +2
    -0
      vendor/golang.org/x/net/ipv4/sys_solaris.go
  91. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_aix_ppc64.go
  92. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_darwin.go
  93. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
  94. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
  95. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
  96. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
  97. +0
    -4
      vendor/golang.org/x/net/ipv4/zsys_freebsd_arm64.go
  98. +0
    -2
      vendor/golang.org/x/net/ipv4/zsys_linux_386.go
  99. +0
    -2
      vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
  100. +0
    -2
      vendor/golang.org/x/net/ipv4/zsys_linux_arm.go

+ 1
- 1
cmd/web_letsencrypt.go View File

@ -32,7 +32,7 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
})
magic.Issuer = myACME
magic.Issuers = []certmagic.Issuer{myACME}
// this obtains certificates or renews them if necessary
err := magic.ManageSync([]string{domain})


+ 6
- 8
go.mod View File

@ -21,7 +21,7 @@ require (
github.com/blevesearch/bleve/v2 v2.0.2
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/caddyserver/certmagic v0.12.0
github.com/caddyserver/certmagic v0.13.0
github.com/chi-middleware/proxy v1.1.1
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
github.com/couchbase/gomemcached v0.1.2 // indirect
@ -75,7 +75,6 @@ require (
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/lafriks/xormstore v1.4.0
github.com/lib/pq v1.9.0
github.com/libdns/libdns v0.2.0 // indirect
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/goth v1.67.1
@ -84,10 +83,9 @@ require (
github.com/mattn/go-sqlite3 v1.14.6
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81
github.com/mgechev/revive v1.0.3
github.com/mholt/acmez v0.1.3 // indirect
github.com/mholt/archiver/v3 v3.5.0
github.com/microcosm-cc/bluemonday v1.0.7
github.com/miekg/dns v1.1.40 // indirect
github.com/miekg/dns v1.1.41 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.10
github.com/minio/sha256-simd v1.0.0 // indirect
@ -135,11 +133,11 @@ require (
go.jolheiser.com/pwn v0.0.3
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0 // indirect
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
golang.org/x/net v0.0.0-20210421230115-4e50805a0758
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44
golang.org/x/text v0.3.5
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08
golang.org/x/text v0.3.6
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.1.0
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect


+ 17
- 15
go.sum View File

@ -185,8 +185,8 @@ github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/caddyserver/certmagic v0.12.0 h1:1f7kxykaJkOVVpXJ8ZrC6RAO5F6+kKm9U7dBFbLNeug=
github.com/caddyserver/certmagic v0.12.0/go.mod h1:tr26xh+9fY5dN0J6IPAlMj07qpog22PJKa7Nw7j835U=
github.com/caddyserver/certmagic v0.13.0 h1:ky0rntZvIFiUKFdIikYxj31WN+Ts0Od6Wjz83iTzxfc=
github.com/caddyserver/certmagic v0.13.0/go.mod h1:dNOzF4iOB7H9E51xTooMB90vs+2XNVtpnx0liQNsQY4=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -769,7 +769,6 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/libdns/libdns v0.2.0 h1:ewg3ByWrdUrxrje8ChPVMBNcotg7H9LQYg+u5De2RzI=
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
@ -825,7 +824,6 @@ github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc8
github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
github.com/mgechev/revive v1.0.3 h1:z3FL6IFFN3JKzHYHD8O1ExH9g/4lAGJ5x1+9rPZgsFg=
github.com/mgechev/revive v1.0.3/go.mod h1:POGGZagSo/0frdr7VeAifzS5Uka0d0GPiM35MsTO8nE=
github.com/mholt/acmez v0.1.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk=
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE=
@ -834,8 +832,8 @@ github.com/microcosm-cc/bluemonday v1.0.7 h1:6yAQfk4XT+PI/dk1ZeBp1gr3Q2Hd1DR0O3a
github.com/microcosm-cc/bluemonday v1.0.7/go.mod h1:HOT/6NaBlR0f9XlxD3zolN6Z3N8Lp4pvhp+jLS5ihnI=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
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/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
@ -1113,8 +1111,6 @@ github.com/unknwon/i18n v0.0.0-20210321134014-0ebbf2df1c44 h1:7bSo/vjZKVYUoZfxpY
github.com/unknwon/i18n v0.0.0-20210321134014-0ebbf2df1c44/go.mod h1:+5rDk6sDGpl3azws3O+f+GpFSyN9GVr0K8cvQLQM2ZQ=
github.com/unknwon/paginater v0.0.0-20200328080006-042474bd0eae h1:ihaXiJkaca54IaCSnEXtE/uSZOmPxKZhDfVLrzZLFDs=
github.com/unknwon/paginater v0.0.0-20200328080006-042474bd0eae/go.mod h1:1fdkY6xxl6ExVs2QFv7R0F5IRZHKA8RahhB9fMC9RvM=
github.com/unrolled/render v1.0.3 h1:baO+NG1bZSF2WR4zwh+0bMWauWky7DVrTOfvE2w+aFo=
github.com/unrolled/render v1.0.3/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM=
github.com/unrolled/render v1.1.0 h1:gvpR9hHxTt6DcGqRYuVVFcfd8rtK+nyEPUJN06KB57Q=
github.com/unrolled/render v1.1.0/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
@ -1231,8 +1227,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/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=
@ -1321,9 +1317,10 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
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/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1346,8 +1343,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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-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=
@ -1419,8 +1417,11 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
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-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 h1:qyN5bV+96OX8pL78eXDuz6YlDPzCYgdW74H5yE9BoSU=
golang.org/x/sys v0.0.0-20210421221651-33663a62ff08/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 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -1430,8 +1431,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
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.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/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-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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=


+ 3
- 3
vendor/github.com/caddyserver/certmagic/README.md View File

@ -260,7 +260,7 @@ magic := certmagic.New(cache, certmagic.Config{
// any customizations you need go here
})
myACME := certmagic.NewACMEManager(magic, ACMEManager{
myACME := certmagic.NewACMEManager(magic, certmagic.ACMEManager{
CA: certmagic.LetsEncryptStagingCA,
Email: "you@yours.com",
Agreed: true,
@ -285,7 +285,7 @@ tlsConfig := magic.TLSConfig()
// we can simply set its GetCertificate field and append the
// TLS-ALPN challenge protocol to the NextProtos
myTLSConfig.GetCertificate = magic.GetCertificate
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol}
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol)
// the HTTP challenge has to be handled by your HTTP server;
// if you don't have one, you should have disabled it earlier
@ -394,7 +394,7 @@ To enable it, just set the `DNS01Solver` field on a `certmagic.ACMEManager` stru
import "github.com/libdns/cloudflare"
certmagic.DefaultACME.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: cloudflare.Provider{
DNSProvider: &cloudflare.Provider{
APIToken: "topsecret",
},
}


+ 85
- 54
vendor/github.com/caddyserver/certmagic/account.go View File

@ -16,6 +16,8 @@ package certmagic
import (
"bufio"
"bytes"
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
@ -33,18 +35,24 @@ import (
// getAccount either loads or creates a new account, depending on if
// an account can be found in storage for the given CA + email combo.
func (am *ACMEManager) getAccount(ca, email string) (acme.Account, error) {
regBytes, err := am.config.Storage.Load(am.storageKeyUserReg(ca, email))
acct, err := am.loadAccount(ca, email)
if err != nil {
if _, ok := err.(ErrNotExist); ok {
return am.newAccount(email)
}
return acct, err
}
return acct, err
}
// loadAccount loads an account from storage, but does not create a new one.
func (am *ACMEManager) loadAccount(ca, email string) (acme.Account, error) {
regBytes, err := am.config.Storage.Load(am.storageKeyUserReg(ca, email))
if err != nil {
return acme.Account{}, err
}
keyBytes, err := am.config.Storage.Load(am.storageKeyUserPrivateKey(ca, email))
if err != nil {
if _, ok := err.(ErrNotExist); ok {
return am.newAccount(email)
}
return acme.Account{}, err
}
@ -58,54 +66,6 @@ func (am *ACMEManager) getAccount(ca, email string) (acme.Account, error) {
return acct, fmt.Errorf("could not decode account's private key: %v", err)
}
// TODO: July 2020 - transition to new ACME lib and account structure;
// for a while, we will need to convert old accounts to new structure
acct, err = am.transitionAccountToACMEzJuly2020Format(ca, acct, regBytes)
if err != nil {
return acct, fmt.Errorf("one-time account transition: %v", err)
}
return acct, err
}
// TODO: this is a temporary transition helper starting July 2020.
// It can go away when we think enough time has passed that most active assets have transitioned.
func (am *ACMEManager) transitionAccountToACMEzJuly2020Format(ca string, acct acme.Account, regBytes []byte) (acme.Account, error) {
if acct.Status != "" && acct.Location != "" {
return acct, nil
}
var oldAcct struct {
Email string `json:"Email"`
Registration struct {
Body struct {
Status string `json:"status"`
TermsOfServiceAgreed bool `json:"termsOfServiceAgreed"`
Orders string `json:"orders"`
ExternalAccountBinding json.RawMessage `json:"externalAccountBinding"`
} `json:"body"`
URI string `json:"uri"`
} `json:"Registration"`
}
err := json.Unmarshal(regBytes, &oldAcct)
if err != nil {
return acct, fmt.Errorf("decoding into old account type: %v", err)
}
acct.Status = oldAcct.Registration.Body.Status
acct.TermsOfServiceAgreed = oldAcct.Registration.Body.TermsOfServiceAgreed
acct.Location = oldAcct.Registration.URI
acct.ExternalAccountBinding = oldAcct.Registration.Body.ExternalAccountBinding
acct.Orders = oldAcct.Registration.Body.Orders
if oldAcct.Email != "" {
acct.Contact = []string{"mailto:" + oldAcct.Email}
}
err = am.saveAccount(ca, acct)
if err != nil {
return acct, fmt.Errorf("saving converted account: %v", err)
}
return acct, nil
}
@ -124,6 +84,71 @@ func (*ACMEManager) newAccount(email string) (acme.Account, error) {
return acct, nil
}
// GetAccount first tries loading the account with the associated private key from storage.
// If it does not exist in storage, it will be retrieved from the ACME server and added to storage.
// The account must already exist; it does not create a new account.
func (am *ACMEManager) GetAccount(ctx context.Context, privateKeyPEM []byte) (acme.Account, error) {
account, err := am.loadAccountByKey(ctx, privateKeyPEM)
if err != nil {
if _, ok := err.(ErrNotExist); ok {
account, err = am.lookUpAccount(ctx, privateKeyPEM)
} else {
return account, err
}
}
return account, err
}
// loadAccountByKey loads the account with the given private key from storage, if it exists.
// If it does not exist, an error of type ErrNotExist is returned. This is not very efficient
// for lots of accounts.
func (am *ACMEManager) loadAccountByKey(ctx context.Context, privateKeyPEM []byte) (acme.Account, error) {
accountList, err := am.config.Storage.List(am.storageKeyUsersPrefix(am.CA), false)
if err != nil {
return acme.Account{}, err
}
for _, accountFolderKey := range accountList {
email := path.Base(accountFolderKey)
keyBytes, err := am.config.Storage.Load(am.storageKeyUserPrivateKey(am.CA, email))
if err != nil {
return acme.Account{}, err
}
if bytes.Equal(bytes.TrimSpace(keyBytes), bytes.TrimSpace(privateKeyPEM)) {
return am.loadAccount(am.CA, email)
}
}
return acme.Account{}, ErrNotExist(fmt.Errorf("no account found with that key"))
}
// lookUpAccount looks up the account associated with privateKeyPEM from the ACME server.
// If the account is found by the server, it will be saved to storage and returned.
func (am *ACMEManager) lookUpAccount(ctx context.Context, privateKeyPEM []byte) (acme.Account, error) {
client, err := am.newACMEClient(false)
if err != nil {
return acme.Account{}, fmt.Errorf("creating ACME client: %v", err)
}
privateKey, err := decodePrivateKey([]byte(privateKeyPEM))
if err != nil {
return acme.Account{}, fmt.Errorf("decoding private key: %v", err)
}
// look up the account
account := acme.Account{PrivateKey: privateKey}
account, err = client.GetAccount(ctx, account)
if err != nil {
return acme.Account{}, fmt.Errorf("looking up account with server: %v", err)
}
// save the account details to storage
err = am.saveAccount(client.Directory, account)
if err != nil {
return account, fmt.Errorf("could not save account to storage: %v", err)
}
return account, nil
}
// saveAccount persists an ACME account's info and private key to storage.
// It does NOT register the account via ACME or prompt the user.
func (am *ACMEManager) saveAccount(ca string, account acme.Account) error {
@ -242,8 +267,12 @@ func (am *ACMEManager) askUserAgreement(agreementURL string) bool {
return answer == "y" || answer == "yes"
}
func storageKeyACMECAPrefix(issuerKey string) string {
return path.Join(prefixACME, StorageKeys.Safe(issuerKey))
}
func (am *ACMEManager) storageKeyCAPrefix(caURL string) string {
return path.Join(prefixACME, StorageKeys.Safe(am.issuerKey(caURL)))
return storageKeyACMECAPrefix(am.issuerKey(caURL))
}
func (am *ACMEManager) storageKeyUsersPrefix(caURL string) string {
@ -305,7 +334,8 @@ func (am *ACMEManager) mostRecentAccountEmail(caURL string) (string, bool) {
// get all the key infos ahead of sorting, because
// we might filter some out
stats := make(map[string]KeyInfo)
for i, u := range accountList {
for i := 0; i < len(accountList); i++ {
u := accountList[i]
keyInfo, err := am.config.Storage.Stat(u)
if err != nil {
continue
@ -318,6 +348,7 @@ func (am *ACMEManager) mostRecentAccountEmail(caURL string) (string, bool) {
// frankly one's OS shouldn't mess with the data folder
// in the first place.
accountList = append(accountList[:i], accountList[i+1:]...)
i--
continue
}
stats[u] = keyInfo


+ 115
- 78
vendor/github.com/caddyserver/certmagic/acmeclient.go View File

@ -37,19 +37,104 @@ func init() {
weakrand.Seed(time.Now().UnixNano())
}
// acmeClient holds state necessary for us to perform
// ACME operations for certificate management. Call
// ACMEManager.newACMEClient() to get a valid one to .
// acmeClient holds state necessary to perform ACME operations
// for certificate management with an ACME account. Call
// ACMEManager.newACMEClientWithAccount() to get a valid one.
type acmeClient struct {
mgr *ACMEManager
acmeClient *acmez.Client
account acme.Account
}
// newACMEClient creates the underlying ACME library client type.
// If useTestCA is true, am.TestCA will be used if it is set;
// otherwise, the primary CA will still be used.
func (am *ACMEManager) newACMEClient(ctx context.Context, useTestCA, interactive bool) (*acmeClient, error) {
// newACMEClientWithAccount creates an ACME client ready to use with an account, including
// loading one from storage or registering a new account with the CA if necessary. If
// useTestCA is true, am.TestCA will be used if set; otherwise, the primary CA will be used.
func (am *ACMEManager) newACMEClientWithAccount(ctx context.Context, useTestCA, interactive bool) (*acmeClient, error) {
// first, get underlying ACME client
client, err := am.newACMEClient(useTestCA)
if err != nil {
return nil, err
}
// look up or create the ACME account
var account acme.Account
if am.AccountKeyPEM != "" {
account, err = am.GetAccount(ctx, []byte(am.AccountKeyPEM))
} else {
account, err = am.getAccount(client.Directory, am.Email)
}
if err != nil {
return nil, fmt.Errorf("getting ACME account: %v", err)
}
// register account if it is new
if account.Status == "" {
if am.NewAccountFunc != nil {
account, err = am.NewAccountFunc(ctx, am, account)
if err != nil {
return nil, fmt.Errorf("account pre-registration callback: %v", err)
}
}
// agree to terms
if interactive {
if !am.Agreed {
var termsURL string
dir, err := client.GetDirectory(ctx)
if err != nil {
return nil, fmt.Errorf("getting directory: %w", err)
}
if dir.Meta != nil {
termsURL = dir.Meta.TermsOfService
}
if termsURL != "" {
am.Agreed = am.askUserAgreement(termsURL)
if !am.Agreed {
return nil, fmt.Errorf("user must agree to CA terms")
}
}
}
} else {
// can't prompt a user who isn't there; they should
// have reviewed the terms beforehand
am.Agreed = true
}
account.TermsOfServiceAgreed = am.Agreed
// associate account with external binding, if configured
if am.ExternalAccount != nil {
err := account.SetExternalAccountBinding(ctx, client.Client, *am.ExternalAccount)
if err != nil {
return nil, err
}
}
// create account
account, err = client.NewAccount(ctx, account)
if err != nil {
return nil, fmt.Errorf("registering account %v with server: %w", account.Contact, err)
}
// persist the account to storage
err = am.saveAccount(client.Directory, account)
if err != nil {
return nil, fmt.Errorf("could not save account %v: %v", account.Contact, err)
}
}
c := &acmeClient{
mgr: am,
acmeClient: client,
account: account,
}
return c, nil
}
// newACMEClient creates a new underlying ACME client using the settings in am,
// independent of any particular ACME account. If useTestCA is true, am.TestCA
// will be used if it is set; otherwise, the primary CA will be used.
func (am *ACMEManager) newACMEClient(useTestCA bool) (*acmez.Client, error) {
// ensure defaults are filled in
var caURL string
if useTestCA {
@ -78,12 +163,6 @@ func (am *ACMEManager) newACMEClient(ctx context.Context, useTestCA, interactive
return nil, fmt.Errorf("%s: insecure CA URL (HTTPS required)", caURL)
}
// look up or create the ACME account
account, err := am.getAccount(caURL, am.Email)
if err != nil {
return nil, fmt.Errorf("getting ACME account: %v", err)
}
// set up the dialers and resolver for the ACME client's HTTP client
dialer := &net.Dialer{
Timeout: 30 * time.Second,
@ -153,12 +232,12 @@ func (am *ACMEManager) newACMEClient(ctx context.Context, useTestCA, interactive
useHTTPPort = am.AltHTTPPort
}
client.ChallengeSolvers[acme.ChallengeTypeHTTP01] = distributedSolver{
acmeManager: am,
storage: am.config.Storage,
storageKeyIssuerPrefix: am.storageKeyCAPrefix(client.Directory),
solver: &httpSolver{
acmeManager: am,
address: net.JoinHostPort(am.ListenHost, strconv.Itoa(useHTTPPort)),
},
caURL: client.Directory,
}
}
@ -172,12 +251,12 @@ func (am *ACMEManager) newACMEClient(ctx context.Context, useTestCA, interactive
useTLSALPNPort = am.AltTLSALPNPort
}
client.ChallengeSolvers[acme.ChallengeTypeTLSALPN01] = distributedSolver{
acmeManager: am,
storage: am.config.Storage,
storageKeyIssuerPrefix: am.storageKeyCAPrefix(client.Directory),
solver: &tlsALPNSolver{
config: am.config,
address: net.JoinHostPort(am.ListenHost, strconv.Itoa(useTLSALPNPort)),
},
caURL: client.Directory,
}
}
} else {
@ -185,68 +264,26 @@ func (am *ACMEManager) newACMEClient(ctx context.Context, useTestCA, interactive
client.ChallengeSolvers[acme.ChallengeTypeDNS01] = am.DNS01Solver
}
// register account if it is new
if account.Status == "" {
if am.NewAccountFunc != nil {
err = am.NewAccountFunc(ctx, am, account)
if err != nil {
return nil, fmt.Errorf("account pre-registration callback: %v", err)
}
}
// agree to terms
if interactive {
if !am.Agreed {
var termsURL string
dir, err := client.GetDirectory(ctx)
if err != nil {
return nil, fmt.Errorf("getting directory: %w", err)
}
if dir.Meta != nil {
termsURL = dir.Meta.TermsOfService
}
if termsURL != "" {
am.Agreed = am.askUserAgreement(termsURL)
if !am.Agreed {
return nil, fmt.Errorf("user must agree to CA terms")
}
}
}
} else {
// can't prompt a user who isn't there; they should
// have reviewed the terms beforehand
am.Agreed = true
}
account.TermsOfServiceAgreed = am.Agreed
// associate account with external binding, if configured
if am.ExternalAccount != nil {
err := account.SetExternalAccountBinding(ctx, client.Client, *am.ExternalAccount)
if err != nil {
return nil, err
}
}
// create account
account, err = client.NewAccount(ctx, account)
if err != nil {
return nil, fmt.Errorf("registering account with server: %w", err)
}
// persist the account to storage
err = am.saveAccount(caURL, account)
if err != nil {
return nil, fmt.Errorf("could not save account: %v", err)
}
}
c := &acmeClient{
mgr: am,
acmeClient: client,
account: account,
// wrap solvers in our wrapper so that we can keep track of challenge
// info: this is useful for solving challenges globally as a process;
// for example, usually there is only one process that can solve the
// HTTP and TLS-ALPN challenges, and only one server in that process
// that can bind the necessary port(s), so if a server listening on
// a different port needed a certificate, it would have to know about
// the other server listening on that port, and somehow convey its
// challenge info or share its config, but this isn't always feasible;
// what the wrapper does is it accesses a global challenge memory so
// that unrelated servers in this process can all solve each others'
// challenges without having to know about each other - Caddy's admin
// endpoint uses this functionality since it and the HTTP/TLS modules
// do not know about each other
// (doing this here in a separate loop ensures that even if we expose
// solver config to users later, we will even wrap their own solvers)
for name, solver := range client.ChallengeSolvers {
client.ChallengeSolvers[name] = solverWrapper{solver}
}
return c, nil
return client, nil
}
func (c *acmeClient) throttle(ctx context.Context, names []string) error {
@ -325,7 +362,7 @@ var (
// RateLimitEvents is how many new events can be allowed
// in RateLimitEventsWindow.
RateLimitEvents = 10
RateLimitEvents = 20
// RateLimitEventsWindow is the size of the sliding
// window that throttles events.


+ 135
- 19
vendor/github.com/caddyserver/certmagic/acmemanager.go View File

@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
@ -19,7 +20,7 @@ import (
// Issuer, and Revoker interfaces.
//
// It is NOT VALID to use an ACMEManager without calling NewACMEManager().
// It fills in default values from DefaultACME as well as setting up
// It fills in any default values from DefaultACME as well as setting up
// internal state that is necessary for valid use. Always call
// NewACMEManager() to get a valid ACMEManager value.
type ACMEManager struct {
@ -37,6 +38,12 @@ type ACMEManager struct {
// selecting an existing ACME server account
Email string
// The PEM-encoded private key of the ACME
// account to use; only needed if the account
// is already created on the server and
// can be looked up with the ACME protocol
AccountKeyPEM string
// Set to true if agreed to the CA's
// subscriber agreement
Agreed bool
@ -92,9 +99,13 @@ type ACMEManager struct {
// Callback function that is called before a
// new ACME account is registered with the CA;
// it allows for last-second config changes
// of the ACMEManager (TODO: this feature is
// still EXPERIMENTAL and subject to change)
NewAccountFunc func(context.Context, *ACMEManager, acme.Account) error
// of the ACMEManager and the Account.
// (TODO: this feature is still EXPERIMENTAL and subject to change)
NewAccountFunc func(context.Context, *ACMEManager, acme.Account) (acme.Account, error)
// Preferences for selecting alternate
// certificate chains
PreferredChains ChainPreference
// Set a logger to enable logging
Logger *zap.Logger
@ -105,10 +116,12 @@ type ACMEManager struct {
// NewACMEManager constructs a valid ACMEManager based on a template
// configuration; any empty values will be filled in by defaults in
// DefaultACME. The associated config is also required.
// DefaultACME, and if any required values are still empty, sensible
// defaults will be used.
//
// Typically, you'll create the Config first, then call NewACMEManager(),
// then assign the return value to the Issuer/Revoker fields of the Config.
// Typically, you'll create the Config first with New() or NewDefault(),
// then call NewACMEManager(), then assign the return value to the Issuers
// field of the Config.
func NewACMEManager(cfg *Config, template ACMEManager) *ACMEManager {
if cfg == nil {
panic("cannot make valid ACMEManager without an associated CertMagic config")
@ -126,6 +139,9 @@ func NewACMEManager(cfg *Config, template ACMEManager) *ACMEManager {
if template.Email == "" {
template.Email = DefaultACME.Email
}
if template.AccountKeyPEM == "" {
template.AccountKeyPEM = DefaultACME.AccountKeyPEM
}
if !template.Agreed {
template.Agreed = DefaultACME.Agreed
}
@ -175,7 +191,7 @@ func (am *ACMEManager) IssuerKey() string {
return am.issuerKey(am.CA)
}
func (am *ACMEManager) issuerKey(ca string) string {
func (*ACMEManager) issuerKey(ca string) string {
key := ca
if caURL, err := url.Parse(key); err == nil {
key = caURL.Host
@ -202,11 +218,11 @@ func (am *ACMEManager) issuerKey(ca string) string {
// batch is eligible for certificates if using Let's Encrypt.
// It also ensures that an email address is available.
func (am *ACMEManager) PreCheck(_ context.Context, names []string, interactive bool) error {
letsEncrypt := strings.Contains(am.CA, "api.letsencrypt.org")
if letsEncrypt {
publicCA := strings.Contains(am.CA, "api.letsencrypt.org") || strings.Contains(am.CA, "acme.zerossl.com")
if publicCA {
for _, name := range names {
if !SubjectQualifiesForPublicCert(name) {
return fmt.Errorf("subject does not qualify for a Let's Encrypt certificate: %s", name)
return fmt.Errorf("subject does not qualify for a public certificate: %s", name)
}
}
}
@ -282,7 +298,7 @@ func (am *ACMEManager) Issue(ctx context.Context, csr *x509.CertificateRequest)
}
func (am *ACMEManager) doIssue(ctx context.Context, csr *x509.CertificateRequest, useTestCA bool) (*IssuedCertificate, bool, error) {
client, err := am.newACMEClient(ctx, useTestCA, false)
client, err := am.newACMEClientWithAccount(ctx, useTestCA, false)
if err != nil {
return nil, false, err
}
@ -300,20 +316,103 @@ func (am *ACMEManager) doIssue(ctx context.Context, csr *x509.CertificateRequest
if err != nil {
return nil, usingTestCA, fmt.Errorf("%v %w (ca=%s)", nameSet, err, client.acmeClient.Directory)
}
if len(certChains) == 0 {
return nil, usingTestCA, fmt.Errorf("no certificate chains")
}
preferredChain := am.selectPreferredChain(certChains)
// TODO: ACME server could in theory issue a cert with multiple chains,
// but we don't (yet) have a way to choose one, so just use first one
ic := &IssuedCertificate{
Certificate: certChains[0].ChainPEM,
Metadata: certChains[0],
Certificate: preferredChain.ChainPEM,
Metadata: preferredChain,
}
return ic, usingTestCA, nil
}
// selectPreferredChain sorts and then filters the certificate chains to find the optimal
// chain preferred by the client. If there's only one chain, that is returned without any
// processing. If there are no matches, the first chain is returned.
func (am *ACMEManager) selectPreferredChain(certChains []acme.Certificate) acme.Certificate {
if len(certChains) == 1 {
if am.Logger != nil && (len(am.PreferredChains.AnyCommonName) > 0 || len(am.PreferredChains.RootCommonName) > 0) {
am.Logger.Debug("there is only one chain offered; selecting it regardless of preferences",
zap.String("chain_url", certChains[0].URL))
}
return certChains[0]
}
if am.PreferredChains.Smallest != nil {
if *am.PreferredChains.Smallest {
sort.Slice(certChains, func(i, j int) bool {
return len(certChains[i].ChainPEM) < len(certChains[j].ChainPEM)
})
} else {
sort.Slice(certChains, func(i, j int) bool {
return len(certChains[i].ChainPEM) > len(certChains[j].ChainPEM)
})
}
}
if len(am.PreferredChains.AnyCommonName) > 0 || len(am.PreferredChains.RootCommonName) > 0 {
// in order to inspect, we need to decode their PEM contents
decodedChains := make([][]*x509.Certificate, len(certChains))
for i, chain := range certChains {
certs, err := parseCertsFromPEMBundle(chain.ChainPEM)
if err != nil {
if am.Logger != nil {
am.Logger.Error("unable to parse PEM certificate chain",
zap.Int("chain", i),
zap.Error(err))
}
continue
}
decodedChains[i] = certs
}
if len(am.PreferredChains.AnyCommonName) > 0 {
for _, prefAnyCN := range am.PreferredChains.AnyCommonName {
for i, chain := range decodedChains {
for _, cert := range chain {
if cert.Issuer.CommonName == prefAnyCN {
if am.Logger != nil {
am.Logger.Debug("found preferred certificate chain by issuer common name",
zap.String("preference", prefAnyCN),
zap.Int("chain", i))
}
return certChains[i]
}
}
}
}
}
if len(am.PreferredChains.RootCommonName) > 0 {
for _, prefRootCN := range am.PreferredChains.RootCommonName {
for i, chain := range decodedChains {
if chain[len(chain)-1].Issuer.CommonName == prefRootCN {
if am.Logger != nil {
am.Logger.Debug("found preferred certificate chain by root common name",
zap.String("preference", prefRootCN),
zap.Int("chain", i))
}
return certChains[i]
}
}
}
}
if am.Logger != nil {
am.Logger.Warn("did not find chain matching preferences; using first")
}
}
return certChains[0]
}
// Revoke implements the Revoker interface. It revokes the given certificate.
func (am *ACMEManager) Revoke(ctx context.Context, cert CertificateResource, reason int) error {
client, err := am.newACMEClient(ctx, false, false)
client, err := am.newACMEClientWithAccount(ctx, false, false)
if err != nil {
return err
}
@ -326,8 +425,24 @@ func (am *ACMEManager) Revoke(ctx context.Context, cert CertificateResource, rea
return client.revoke(ctx, certs[0], reason)
}
// DefaultACME specifies the default settings
// to use for ACMEManagers.
// ChainPreference describes the client's preferred certificate chain,
// useful if the CA offers alternate chains. The first matching chain
// will be selected.
type ChainPreference struct {
// Prefer chains with the fewest number of bytes.
Smallest *bool
// Select first chain having a root with one of
// these common names.
RootCommonName []string
// Select first chain that has any issuer with one
// of these common names.
AnyCommonName []string
}
// DefaultACME specifies default settings to use for ACMEManagers.
// Using this value is optional but can be convenient.
var DefaultACME = ACMEManager{
CA: LetsEncryptProductionCA,
TestCA: LetsEncryptStagingCA,
@ -337,6 +452,7 @@ var DefaultACME = ACMEManager{
const (
LetsEncryptStagingCA = "https://acme-staging-v02.api.letsencrypt.org/directory"
LetsEncryptProductionCA = "https://acme-v02.api.letsencrypt.org/directory"
ZeroSSLProductionCA = "https://acme.zerossl.com/v2/DV90"
)
// prefixACME is the storage key prefix used for ACME-specific assets.


+ 39
- 31
vendor/github.com/caddyserver/certmagic/certificates.go View File

@ -113,10 +113,11 @@ func (cfg *Config) CacheManagedCertificate(domain string) (Certificate, error) {
return cert, nil
}
// loadManagedCertificate loads the managed certificate for domain,
// but it does not add it to the cache. It just loads from storage.
// loadManagedCertificate loads the managed certificate for domain from any
// of the configured issuers' storage locations, but it does not add it to
// the cache. It just loads from storage and returns it.
func (cfg *Config) loadManagedCertificate(domain string) (Certificate, error) {
certRes, err := cfg.loadCertResource(domain)
certRes, err := cfg.loadCertResourceAnyIssuer(domain)
if err != nil {
return Certificate{}, err
}
@ -154,7 +155,7 @@ func (cfg *Config) CacheUnmanagedTLSCertificate(tlsCert tls.Certificate, tags []
if err != nil {
return err
}
_, err = stapleOCSP(cfg.Storage, &cert, nil)
_, err = stapleOCSP(cfg.OCSP, cfg.Storage, &cert, nil)
if err != nil && cfg.Logger != nil {
cfg.Logger.Warn("stapling OCSP", zap.Error(err))
}
@ -202,7 +203,7 @@ func (cfg Config) makeCertificateWithOCSP(certPEMBlock, keyPEMBlock []byte) (Cer
if err != nil {
return cert, err
}
_, err = stapleOCSP(cfg.Storage, &cert, certPEMBlock)
_, err = stapleOCSP(cfg.OCSP, cfg.Storage, &cert, certPEMBlock)
if err != nil && cfg.Logger != nil {
cfg.Logger.Warn("stapling OCSP", zap.Error(err))
}
@ -295,19 +296,12 @@ func fillCertFromLeaf(cert *Certificate, tlsCert tls.Certificate) error {
// meantime, and it would be a good idea to simply load the cert
// into our cache rather than repeating the renewal process again.
func (cfg *Config) managedCertInStorageExpiresSoon(cert Certificate) (bool, error) {
certRes, err := cfg.loadCertResource(cert.Names[0])
certRes, err := cfg.loadCertResourceAnyIssuer(cert.Names[0])
if err != nil {
return false, err
}
tlsCert, err := tls.X509KeyPair(certRes.CertificatePEM, certRes.PrivateKeyPEM)
if err != nil {
return false, err
}
leaf, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
return false, err
}
return currentlyInRenewalWindow(leaf.NotBefore, leaf.NotAfter, cfg.RenewalWindowRatio), nil
_, needsRenew := cfg.managedCertNeedsRenewal(certRes)
return needsRenew, nil
}
// reloadManagedCertificate reloads the certificate corresponding to the name(s)
@ -341,8 +335,9 @@ func SubjectQualifiesForCert(subj string) bool {
!strings.HasPrefix(subj, ".") &&
!strings.HasSuffix(subj, ".") &&
// if it has a wildcard, must be a left-most label
(!strings.Contains(subj, "*") || strings.HasPrefix(subj, "*.")) &&
// if it has a wildcard, must be a left-most label (or exactly "*"
// which won't be trusted by browsers but still technically works)
(!strings.Contains(subj, "*") || strings.HasPrefix(subj, "*.") || subj == "*") &&
// must not contain other common special characters
!strings.ContainsAny(subj, "()[]{}<> \t\n\"\\!@#$%^&|;'+=")
@ -356,32 +351,45 @@ func SubjectQualifiesForCert(subj string) bool {
// allowed, as long as they conform to CABF requirements (only
// one wildcard label, and it must be the left-most label).
func SubjectQualifiesForPublicCert(subj string) bool {
// must at least qualify for certificate
// must at least qualify for a certificate
return SubjectQualifiesForCert(subj) &&
// localhost is ineligible
subj != "localhost" &&
// .localhost TLD is ineligible
!strings.HasSuffix(subj, ".localhost") &&
// localhost, .localhost TLD, and .local TLD are ineligible
!SubjectIsInternal(subj) &&
// .local TLD is ineligible
!strings.HasSuffix(subj, ".local") &&
// cannot be an IP address (as of yet), see
// https://community.letsencrypt.org/t/certificate-for-static-ip/84/2?u=mholt
!SubjectIsIP(subj) &&
// only one wildcard label allowed, and it must be left-most
// only one wildcard label allowed, and it must be left-most, with 3+ labels
(!strings.Contains(subj, "*") ||
(strings.Count(subj, "*") == 1 &&
strings.Count(subj, ".") > 1 &&
len(subj) > 2 &&
strings.HasPrefix(subj, "*."))) &&
strings.HasPrefix(subj, "*.")))
}
// cannot be an IP address (as of yet), see
// https://community.letsencrypt.org/t/certificate-for-static-ip/84/2?u=mholt
net.ParseIP(subj) == nil
// SubjectIsIP returns true if subj is an IP address.
func SubjectIsIP(subj string) bool {
return net.ParseIP(subj) != nil
}
// SubjectIsInternal returns true if subj is an internal-facing
// hostname or address.
func SubjectIsInternal(subj string) bool {
return subj == "localhost" ||
strings.HasSuffix(subj, ".localhost") ||
strings.HasSuffix(subj, ".local")
}
// MatchWildcard returns true if subject (a candidate DNS name)
// matches wildcard (a reference DNS name), mostly according to
// RFC6125-compliant wildcard rules.
// RFC 6125-compliant wildcard rules. See also RFC 2818 which
// states that IP addresses must match exactly, but this function
// does not attempt to distinguish IP addresses from internal or
// external DNS names that happen to look like IP addresses.
// It uses DNS wildcard matching logic.
// https://tools.ietf.org/html/rfc2818#section-3.1
func MatchWildcard(subject, wildcard string) bool {
if subject == wildcard {
return true


+ 15
- 9
vendor/github.com/caddyserver/certmagic/certmagic.go View File

@ -125,8 +125,10 @@ func HTTPS(domainNames []string, mux http.Handler) error {
WriteTimeout: 5 * time.Second,
IdleTimeout: 5 * time.Second,
}
if am, ok := cfg.Issuer.(*ACMEManager); ok {
httpServer.Handler = am.HTTPChallengeHandler(http.HandlerFunc(httpRedirectHandler))
if len(cfg.Issuers) > 0 {
if am, ok := cfg.Issuers[0].(*ACMEManager); ok {
httpServer.Handler = am.HTTPChallengeHandler(http.HandlerFunc(httpRedirectHandler))
}
}
httpsServer := &http.Server{
ReadHeaderTimeout: 10 * time.Second,
@ -425,9 +427,11 @@ func (cr *CertificateResource) NamesKey() string {
// Default contains the package defaults for the
// various Config fields. This is used as a template
// when creating your own Configs with New(), and it
// is also used as the Config by all the high-level
// functions in this package.
// when creating your own Configs with New() or
// NewDefault(), and it is also used as the Config
// by all the high-level functions in this package
// that abstract away most configuration (HTTPS(),
// TLS(), Listen(), etc).
//
// The fields of this value will be used for Config
// fields which are unset. Feel free to modify these
@ -436,8 +440,10 @@ func (cr *CertificateResource) NamesKey() string {
// obtained by calling New() (if you have your own
// certificate cache) or NewDefault() (if you only
// need a single config and want to use the default
// cache). This is the only Config which can access
// the default certificate cache.
// cache).
//
// Even if the Issuers or Storage fields are not set,
// defaults will be applied in the call to New().
var Default = Config{
RenewalWindowRatio: DefaultRenewalWindowRatio,
Storage: defaultFileStorage,
@ -459,12 +465,12 @@ const (
// are set to; otherwise ACME challenges will fail.
var (
// HTTPPort is the port on which to serve HTTP
// and, by extension, the HTTP challenge (unless
// and, as such, the HTTP challenge (unless
// Default.AltHTTPPort is set).
HTTPPort = 80
// HTTPSPort is the port on which to serve HTTPS
// and, by extension, the TLS-ALPN challenge
// and, as such, the TLS-ALPN challenge
// (unless Default.AltTLSALPNPort is set).
HTTPSPort = 443
)


+ 265
- 126
vendor/github.com/caddyserver/certmagic/config.go View File

@ -23,6 +23,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/json"
"fmt"
weakrand "math/rand"
"net"
@ -31,7 +32,9 @@ import (
"time"
"github.com/mholt/acmez"
"github.com/mholt/acmez/acme"
"go.uber.org/zap"
"golang.org/x/net/idna"
)
// Config configures a certificate manager instance.
@ -54,45 +57,48 @@ type Config struct {
// DefaultServerName specifies a server name
// to use when choosing a certificate if the
// ClientHello's ServerName field is empty
// ClientHello's ServerName field is empty.
DefaultServerName string
// The state needed to operate on-demand TLS;
// if non-nil, on-demand TLS is enabled and
// certificate operations are deferred to
// TLS handshakes (or as-needed)
// TLS handshakes (or as-needed).
// TODO: Can we call this feature "Reactive/Lazy/Passive TLS" instead?
OnDemand *OnDemandConfig
// Add the must staple TLS extension to the CSR
// Adds the must staple TLS extension to the CSR.
MustStaple bool
// The type that issues certificates; the
// default Issuer is ACMEManager
Issuer Issuer
// The type that revokes certificates; must
// be configured in conjunction with the Issuer
// field such that both the Issuer and Revoker
// are related (because issuance information is
// required for revocation)
Revoker Revoker
// The source for getting new certificates; the
// default Issuer is ACMEManager. If multiple
// issuers are specified, they will be tried in
// turn until one succeeds.
Issuers []Issuer
// The source of new private keys for certificates;
// the default KeySource is StandardKeyGenerator
// the default KeySource is StandardKeyGenerator.
KeySource KeyGenerator
// CertSelection chooses one of the certificates
// with which the ClientHello will be completed;
// if not set, DefaultCertificateSelector will
// be used
// be used.
CertSelection CertificateSelector
// The storage to access when storing or
// loading TLS assets
// OCSP configures how OCSP is handled. By default,
// OCSP responses are fetched for every certificate
// with a responder URL, and cached on disk. Changing
// these defaults is STRONGLY discouraged unless you
// have a compelling reason to put clients at greater
// risk and reduce their privacy.
OCSP OCSPConfig
// The storage to access when storing or loading
// TLS assets. Default is the local file system.
Storage Storage
// Set a logger to enable logging
// Set a logger to enable logging.
Logger *zap.Logger
// required pointer to the in-memory cert cache
@ -116,6 +122,9 @@ type Config struct {
// same, default certificate cache. All configs returned
// by NewDefault() are based on the values of the fields of
// Default at the time it is called.
//
// This is the only way to get a config that uses the
// default certificate cache.
func NewDefault() *Config {
defaultCacheMu.Lock()
if defaultCache == nil {
@ -153,7 +162,7 @@ func NewDefault() *Config {
// the vast majority of cases, there will be only a
// single Config, thus the default cache (which always
// uses the default Config) and default config will
// suffice, and you should use New() instead.
// suffice, and you should use NewDefault() instead.
func New(certCache *Cache, cfg Config) *Config {
if certCache == nil {
panic("a certificate cache is required")
@ -196,23 +205,11 @@ func newWithCache(certCache *Cache, cfg Config) *Config {
if cfg.Storage == nil {
cfg.Storage = Default.Storage
}
if cfg.Issuer == nil {
cfg.Issuer = Default.Issuer
if cfg.Issuer == nil {
// okay really, we need an issuer,
// that's kind of the point; most
// people would probably want ACME
cfg.Issuer = NewACMEManager(&cfg, DefaultACME)
}
// issuer and revoker go together; if user
// specifies their own issuer, we don't want
// to override their revoker, hence we only
// do this if Issuer was also nil
if cfg.Revoker == nil {
cfg.Revoker = Default.Revoker
if cfg.Revoker == nil {
cfg.Revoker = NewACMEManager(&cfg, DefaultACME)
}
if len(cfg.Issuers) == 0 {
cfg.Issuers = Default.Issuers
if len(cfg.Issuers) == 0 {
// at least one issuer is absolutely required
cfg.Issuers = []Issuer{NewACMEManager(&cfg, DefaultACME)}
}
}
@ -223,7 +220,6 @@ func newWithCache(certCache *Cache, cfg Config) *Config {
cfg.Storage = defaultFileStorage
}
// ensure the unexported fields are valid
cfg.certCache = certCache
return &cfg
@ -254,6 +250,29 @@ func (cfg *Config) ManageSync(domainNames []string) error {
return cfg.manageAll(nil, domainNames, false)
}
// ClientCredentials returns a list of TLS client certificate chains for the given identifiers.
// The return value can be used in a tls.Config to enable client authentication using managed certificates.
// Any certificates that need to be obtained or renewed for these identifiers will be managed accordingly.
func (cfg *Config) ClientCredentials(ctx context.Context, identifiers []string) ([]tls.Certificate, error) {
err := cfg.manageAll(ctx, identifiers, false)
if err != nil {
return nil, err
}
var chains []tls.Certificate
for _, id := range identifiers {
certRes, err := cfg.loadCertResourceAnyIssuer(id)
if err != nil {
return chains, err
}
chain, err := tls.X509KeyPair(certRes.CertificatePEM, certRes.PrivateKeyPEM)
if err != nil {
return chains, err
}
chains = append(chains, chain)
}
return chains, nil
}
// ManageAsync is the same as ManageSync, except that ACME
// operations are performed asynchronously (in the background).
// This method returns before certificates are ready. It is
@ -360,6 +379,28 @@ func (cfg *Config) manageOne(ctx context.Context, domainName string, async bool)
return nil
}
// Unmanage causes the certificates for domainNames to stop being managed.
// If there are certificates for the supplied domain names in the cache, they
// are evicted from the cache.
func (cfg *Config) Unmanage(domainNames []string) {
var deleteQueue []Certificate
for _, domainName := range domainNames {
certs := cfg.certCache.AllMatchingCertificates(domainName)
for _, cert := range certs {
if !cert.managed {
continue
}
deleteQueue = append(deleteQueue, cert)
}
}
cfg.certCache.mu.Lock()
for _, cert := range deleteQueue {
cfg.certCache.removeCertificate(cert)
}
cfg.certCache.mu.Unlock()
}
// ObtainCert obtains a certificate for name using cfg, as long
// as a certificate does not already exist in storage for that
// name. The name must qualify and cfg must be flagged as Managed.
@ -372,27 +413,22 @@ func (cfg *Config) manageOne(ctx context.Context, domainName string, async bool)
// TODO: consider moving interactive param into the Config struct,
// and maybe retry settings into the Config struct as well? (same for RenewCert)
func (cfg *Config) ObtainCert(ctx context.Context, name string, interactive bool) error {
if cfg.storageHasCertResources(name) {
return nil
}
issuer, err := cfg.getPrecheckedIssuer(ctx, []string{name}, interactive)
if err != nil {
return err
if len(cfg.Issuers) == 0 {
return fmt.Errorf("no issuers configured; impossible to obtain or check for existing certificate in storage")
}
if issuer == nil {
if cfg.storageHasCertResourcesAnyIssuer(name) {
return nil
}
return cfg.obtainWithIssuer(ctx, issuer, name, interactive)
}
func loggerNamed(l *zap.Logger, name string) *zap.Logger {
if l == nil {
return nil
// ensure storage is writeable and readable
// TODO: this is not necessary every time; should only perform check once every so often for each storage, which may require some global state...
err := cfg.checkStorage()
if err != nil {
return fmt.Errorf("failed storage check: %v - storage is probably misconfigured", err)
}
return l.Named(name)
return cfg.obtainCert(ctx, name, interactive)
}
func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name string, interactive bool) error {
func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool) error {
log := loggerNamed(cfg.Logger, "obtain")
if log != nil {
@ -400,10 +436,10 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
}
// ensure idempotency of the obtain operation for this name
lockKey := cfg.lockKey("cert_acme", name)
lockKey := cfg.lockKey(certIssueLockOp, name)
err := acquireLock(ctx, cfg.Storage, lockKey)
if err != nil {
return err
return fmt.Errorf("unable to acquire lock '%s': %v", lockKey, err)
}
defer func() {
if log != nil {
@ -424,7 +460,7 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
f := func(ctx context.Context) error {
// check if obtain is still needed -- might have been obtained during lock
if cfg.storageHasCertResources(name) {
if cfg.storageHasCertResourcesAnyIssuer(name) {
if log != nil {
log.Info("certificate already exists in storage", zap.String("identifier", name))
}
@ -445,8 +481,24 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
return err
}
issuedCert, err := issuer.Issue(ctx, csr)
// try to obtain from each issuer until we succeed
var issuedCert *IssuedCertificate
var issuerUsed Issuer
for _, issuer := range cfg.Issuers {
if prechecker, ok := issuer.(PreChecker); ok {
err = prechecker.PreCheck(ctx, []string{name}, interactive)
if err != nil {
continue
}
}
issuedCert, err = issuer.Issue(ctx, csr)
if err == nil {
issuerUsed = issuer
break
}
}
if err != nil {
// TODO: only the error from the last issuer will be returned, oh well?
return fmt.Errorf("[%s] Obtain: %w", name, err)
}
@ -457,7 +509,7 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
PrivateKeyPEM: privKeyPEM,
IssuerData: issuedCert.Metadata,
}
err = cfg.saveCertResource(certRes)
err = cfg.saveCertResource(issuerUsed, certRes)
if err != nil {
return fmt.Errorf("[%s] Obtain: saving assets: %v", name, err)
}
@ -480,21 +532,32 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
return err
}
func (cfg *Config) storageHasCertResourcesAnyIssuer(name string) bool {
for _, iss := range cfg.Issuers {
if cfg.storageHasCertResources(iss, name) {
return true
}
}
return false
}
// RenewCert renews the certificate for name using cfg. It stows the
// renewed certificate and its assets in storage if successful. It
// DOES NOT update the in-memory cache with the new certificate.
func (cfg *Config) RenewCert(ctx context.Context, name string, interactive bool) error {
issuer, err := cfg.getPrecheckedIssuer(ctx, []string{name}, interactive)
if err != nil {
return err
if len(cfg.Issuers) == 0 {
return fmt.Errorf("no issuers configured; impossible to renew or check existing certificate in storage")
}
if issuer == nil {