Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
25e9cfb0
Commit
25e9cfb0
authored
Jul 17, 2019
by
Erik Wilson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update dynamiclistener
parent
2d323373
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
3 additions
and
1201 deletions
+3
-1201
trash.lock
trash.lock
+2
-1
vendor.conf
vendor.conf
+1
-1
read.go
vendor/github.com/rancher/dynamiclistener/read.go
+0
-5
server.go
vendor/github.com/rancher/dynamiclistener/server.go
+0
-0
acme.go
vendor/golang.org/x/crypto/acme/acme.go
+0
-0
autocert.go
vendor/golang.org/x/crypto/acme/autocert/autocert.go
+0
-0
cache.go
vendor/golang.org/x/crypto/acme/autocert/cache.go
+0
-130
listener.go
vendor/golang.org/x/crypto/acme/autocert/listener.go
+0
-160
renewal.go
vendor/golang.org/x/crypto/acme/autocert/renewal.go
+0
-141
http.go
vendor/golang.org/x/crypto/acme/http.go
+0
-281
jws.go
vendor/golang.org/x/crypto/acme/jws.go
+0
-153
types.go
vendor/golang.org/x/crypto/acme/types.go
+0
-329
No files found.
trash.lock
View file @
25e9cfb0
...
...
@@ -225,7 +225,8 @@ import:
- package: github.com/prometheus/procfs
version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259
- package: github.com/rancher/dynamiclistener
version: 4716ac2362986f28bede3f3caf5d1ce347da55b0
version: c08b499d17195fbc2c1764b21c322951811629a5
repo: https://github.com/erikwilson/rancher-dynamiclistener.git
- package: github.com/rancher/helm-controller
version: v0.2.1
- package: github.com/rancher/remotedialer
...
...
vendor.conf
View file @
25e9cfb0
...
...
@@ -13,7 +13,7 @@ k8s.io/kubernetes v1.14.4-k3s.1 ht
github
.
com
/
rancher
/
wrangler
7737
c167e16514a38229bc64c839cee8cd14e6d3
github
.
com
/
rancher
/
wrangler
-
api
v0
.
1
.
4
github
.
com
/
rancher
/
dynamiclistener
4716
ac2362986f28bede3f3caf5d1ce347da55b0
github
.
com
/
rancher
/
dynamiclistener
c08b499d17195fbc2c1764b21c322951811629a5
https
://
github
.
com
/
erikwilson
/
rancher
-
dynamiclistener
.
git
github
.
com
/
rancher
/
remotedialer
4
a5a661be67697d6369df54ef62d5a30b0385697
github
.
com
/
rancher
/
helm
-
controller
v0
.
2
.
1
github
.
com
/
matryer
/
moq
ee5226d43009
https
://
github
.
com
/
rancher
/
moq
.
git
...
...
vendor/github.com/rancher/dynamiclistener/read.go
View file @
25e9cfb0
...
...
@@ -26,11 +26,6 @@ func ReadTLSConfig(userConfig *UserConfig) error {
return
err
}
userConfig
.
Mode
=
"https"
if
len
(
userConfig
.
Domains
)
>
0
{
userConfig
.
Mode
=
"acme"
}
valid
:=
false
if
userConfig
.
Key
!=
""
&&
userConfig
.
Cert
!=
""
{
valid
=
true
...
...
vendor/github.com/rancher/dynamiclistener/server.go
View file @
25e9cfb0
This diff is collapsed.
Click to expand it.
vendor/golang.org/x/crypto/acme/acme.go
deleted
100644 → 0
View file @
2d323373
This diff is collapsed.
Click to expand it.
vendor/golang.org/x/crypto/acme/autocert/autocert.go
deleted
100644 → 0
View file @
2d323373
This diff is collapsed.
Click to expand it.
vendor/golang.org/x/crypto/acme/autocert/cache.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
autocert
import
(
"context"
"errors"
"io/ioutil"
"os"
"path/filepath"
)
// ErrCacheMiss is returned when a certificate is not found in cache.
var
ErrCacheMiss
=
errors
.
New
(
"acme/autocert: certificate cache miss"
)
// Cache is used by Manager to store and retrieve previously obtained certificates
// and other account data as opaque blobs.
//
// Cache implementations should not rely on the key naming pattern. Keys can
// include any printable ASCII characters, except the following: \/:*?"<>|
type
Cache
interface
{
// Get returns a certificate data for the specified key.
// If there's no such key, Get returns ErrCacheMiss.
Get
(
ctx
context
.
Context
,
key
string
)
([]
byte
,
error
)
// Put stores the data in the cache under the specified key.
// Underlying implementations may use any data storage format,
// as long as the reverse operation, Get, results in the original data.
Put
(
ctx
context
.
Context
,
key
string
,
data
[]
byte
)
error
// Delete removes a certificate data from the cache under the specified key.
// If there's no such key in the cache, Delete returns nil.
Delete
(
ctx
context
.
Context
,
key
string
)
error
}
// DirCache implements Cache using a directory on the local filesystem.
// If the directory does not exist, it will be created with 0700 permissions.
type
DirCache
string
// Get reads a certificate data from the specified file name.
func
(
d
DirCache
)
Get
(
ctx
context
.
Context
,
name
string
)
([]
byte
,
error
)
{
name
=
filepath
.
Join
(
string
(
d
),
name
)
var
(
data
[]
byte
err
error
done
=
make
(
chan
struct
{})
)
go
func
()
{
data
,
err
=
ioutil
.
ReadFile
(
name
)
close
(
done
)
}()
select
{
case
<-
ctx
.
Done
()
:
return
nil
,
ctx
.
Err
()
case
<-
done
:
}
if
os
.
IsNotExist
(
err
)
{
return
nil
,
ErrCacheMiss
}
return
data
,
err
}
// Put writes the certificate data to the specified file name.
// The file will be created with 0600 permissions.
func
(
d
DirCache
)
Put
(
ctx
context
.
Context
,
name
string
,
data
[]
byte
)
error
{
if
err
:=
os
.
MkdirAll
(
string
(
d
),
0700
);
err
!=
nil
{
return
err
}
done
:=
make
(
chan
struct
{})
var
err
error
go
func
()
{
defer
close
(
done
)
var
tmp
string
if
tmp
,
err
=
d
.
writeTempFile
(
name
,
data
);
err
!=
nil
{
return
}
select
{
case
<-
ctx
.
Done
()
:
// Don't overwrite the file if the context was canceled.
default
:
newName
:=
filepath
.
Join
(
string
(
d
),
name
)
err
=
os
.
Rename
(
tmp
,
newName
)
}
}()
select
{
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
case
<-
done
:
}
return
err
}
// Delete removes the specified file name.
func
(
d
DirCache
)
Delete
(
ctx
context
.
Context
,
name
string
)
error
{
name
=
filepath
.
Join
(
string
(
d
),
name
)
var
(
err
error
done
=
make
(
chan
struct
{})
)
go
func
()
{
err
=
os
.
Remove
(
name
)
close
(
done
)
}()
select
{
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
case
<-
done
:
}
if
err
!=
nil
&&
!
os
.
IsNotExist
(
err
)
{
return
err
}
return
nil
}
// writeTempFile writes b to a temporary file, closes the file and returns its path.
func
(
d
DirCache
)
writeTempFile
(
prefix
string
,
b
[]
byte
)
(
string
,
error
)
{
// TempFile uses 0600 permissions
f
,
err
:=
ioutil
.
TempFile
(
string
(
d
),
prefix
)
if
err
!=
nil
{
return
""
,
err
}
if
_
,
err
:=
f
.
Write
(
b
);
err
!=
nil
{
f
.
Close
()
return
""
,
err
}
return
f
.
Name
(),
f
.
Close
()
}
vendor/golang.org/x/crypto/acme/autocert/listener.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
autocert
import
(
"crypto/tls"
"log"
"net"
"os"
"path/filepath"
"runtime"
"time"
)
// NewListener returns a net.Listener that listens on the standard TLS
// port (443) on all interfaces and returns *tls.Conn connections with
// LetsEncrypt certificates for the provided domain or domains.
//
// It enables one-line HTTPS servers:
//
// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
//
// NewListener is a convenience function for a common configuration.
// More complex or custom configurations can use the autocert.Manager
// type instead.
//
// Use of this function implies acceptance of the LetsEncrypt Terms of
// Service. If domains is not empty, the provided domains are passed
// to HostWhitelist. If domains is empty, the listener will do
// LetsEncrypt challenges for any requested domain, which is not
// recommended.
//
// Certificates are cached in a "golang-autocert" directory under an
// operating system-specific cache or temp directory. This may not
// be suitable for servers spanning multiple machines.
//
// The returned listener uses a *tls.Config that enables HTTP/2, and
// should only be used with servers that support HTTP/2.
//
// The returned Listener also enables TCP keep-alives on the accepted
// connections. The returned *tls.Conn are returned before their TLS
// handshake has completed.
func
NewListener
(
domains
...
string
)
net
.
Listener
{
m
:=
&
Manager
{
Prompt
:
AcceptTOS
,
}
if
len
(
domains
)
>
0
{
m
.
HostPolicy
=
HostWhitelist
(
domains
...
)
}
dir
:=
cacheDir
()
if
err
:=
os
.
MkdirAll
(
dir
,
0700
);
err
!=
nil
{
log
.
Printf
(
"warning: autocert.NewListener not using a cache: %v"
,
err
)
}
else
{
m
.
Cache
=
DirCache
(
dir
)
}
return
m
.
Listener
()
}
// Listener listens on the standard TLS port (443) on all interfaces
// and returns a net.Listener returning *tls.Conn connections.
//
// The returned listener uses a *tls.Config that enables HTTP/2, and
// should only be used with servers that support HTTP/2.
//
// The returned Listener also enables TCP keep-alives on the accepted
// connections. The returned *tls.Conn are returned before their TLS
// handshake has completed.
//
// Unlike NewListener, it is the caller's responsibility to initialize
// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
func
(
m
*
Manager
)
Listener
()
net
.
Listener
{
ln
:=
&
listener
{
m
:
m
,
conf
:
&
tls
.
Config
{
GetCertificate
:
m
.
GetCertificate
,
// bonus: panic on nil m
NextProtos
:
[]
string
{
"h2"
,
"http/1.1"
},
// Enable HTTP/2
},
}
ln
.
tcpListener
,
ln
.
tcpListenErr
=
net
.
Listen
(
"tcp"
,
":443"
)
return
ln
}
type
listener
struct
{
m
*
Manager
conf
*
tls
.
Config
tcpListener
net
.
Listener
tcpListenErr
error
}
func
(
ln
*
listener
)
Accept
()
(
net
.
Conn
,
error
)
{
if
ln
.
tcpListenErr
!=
nil
{
return
nil
,
ln
.
tcpListenErr
}
conn
,
err
:=
ln
.
tcpListener
.
Accept
()
if
err
!=
nil
{
return
nil
,
err
}
tcpConn
:=
conn
.
(
*
net
.
TCPConn
)
// Because Listener is a convenience function, help out with
// this too. This is not possible for the caller to set once
// we return a *tcp.Conn wrapping an inaccessible net.Conn.
// If callers don't want this, they can do things the manual
// way and tweak as needed. But this is what net/http does
// itself, so copy that. If net/http changes, we can change
// here too.
tcpConn
.
SetKeepAlive
(
true
)
tcpConn
.
SetKeepAlivePeriod
(
3
*
time
.
Minute
)
return
tls
.
Server
(
tcpConn
,
ln
.
conf
),
nil
}
func
(
ln
*
listener
)
Addr
()
net
.
Addr
{
if
ln
.
tcpListener
!=
nil
{
return
ln
.
tcpListener
.
Addr
()
}
// net.Listen failed. Return something non-nil in case callers
// call Addr before Accept:
return
&
net
.
TCPAddr
{
IP
:
net
.
IP
{
0
,
0
,
0
,
0
},
Port
:
443
}
}
func
(
ln
*
listener
)
Close
()
error
{
if
ln
.
tcpListenErr
!=
nil
{
return
ln
.
tcpListenErr
}
return
ln
.
tcpListener
.
Close
()
}
func
homeDir
()
string
{
if
runtime
.
GOOS
==
"windows"
{
return
os
.
Getenv
(
"HOMEDRIVE"
)
+
os
.
Getenv
(
"HOMEPATH"
)
}
if
h
:=
os
.
Getenv
(
"HOME"
);
h
!=
""
{
return
h
}
return
"/"
}
func
cacheDir
()
string
{
const
base
=
"golang-autocert"
switch
runtime
.
GOOS
{
case
"darwin"
:
return
filepath
.
Join
(
homeDir
(),
"Library"
,
"Caches"
,
base
)
case
"windows"
:
for
_
,
ev
:=
range
[]
string
{
"APPDATA"
,
"CSIDL_APPDATA"
,
"TEMP"
,
"TMP"
}
{
if
v
:=
os
.
Getenv
(
ev
);
v
!=
""
{
return
filepath
.
Join
(
v
,
base
)
}
}
// Worst case:
return
filepath
.
Join
(
homeDir
(),
base
)
}
if
xdg
:=
os
.
Getenv
(
"XDG_CACHE_HOME"
);
xdg
!=
""
{
return
filepath
.
Join
(
xdg
,
base
)
}
return
filepath
.
Join
(
homeDir
(),
".cache"
,
base
)
}
vendor/golang.org/x/crypto/acme/autocert/renewal.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
autocert
import
(
"context"
"crypto"
"sync"
"time"
)
// renewJitter is the maximum deviation from Manager.RenewBefore.
const
renewJitter
=
time
.
Hour
// domainRenewal tracks the state used by the periodic timers
// renewing a single domain's cert.
type
domainRenewal
struct
{
m
*
Manager
ck
certKey
key
crypto
.
Signer
timerMu
sync
.
Mutex
timer
*
time
.
Timer
}
// start starts a cert renewal timer at the time
// defined by the certificate expiration time exp.
//
// If the timer is already started, calling start is a noop.
func
(
dr
*
domainRenewal
)
start
(
exp
time
.
Time
)
{
dr
.
timerMu
.
Lock
()
defer
dr
.
timerMu
.
Unlock
()
if
dr
.
timer
!=
nil
{
return
}
dr
.
timer
=
time
.
AfterFunc
(
dr
.
next
(
exp
),
dr
.
renew
)
}
// stop stops the cert renewal timer.
// If the timer is already stopped, calling stop is a noop.
func
(
dr
*
domainRenewal
)
stop
()
{
dr
.
timerMu
.
Lock
()
defer
dr
.
timerMu
.
Unlock
()
if
dr
.
timer
==
nil
{
return
}
dr
.
timer
.
Stop
()
dr
.
timer
=
nil
}
// renew is called periodically by a timer.
// The first renew call is kicked off by dr.start.
func
(
dr
*
domainRenewal
)
renew
()
{
dr
.
timerMu
.
Lock
()
defer
dr
.
timerMu
.
Unlock
()
if
dr
.
timer
==
nil
{
return
}
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Minute
)
defer
cancel
()
// TODO: rotate dr.key at some point?
next
,
err
:=
dr
.
do
(
ctx
)
if
err
!=
nil
{
next
=
renewJitter
/
2
next
+=
time
.
Duration
(
pseudoRand
.
int63n
(
int64
(
next
)))
}
dr
.
timer
=
time
.
AfterFunc
(
next
,
dr
.
renew
)
testDidRenewLoop
(
next
,
err
)
}
// updateState locks and replaces the relevant Manager.state item with the given
// state. It additionally updates dr.key with the given state's key.
func
(
dr
*
domainRenewal
)
updateState
(
state
*
certState
)
{
dr
.
m
.
stateMu
.
Lock
()
defer
dr
.
m
.
stateMu
.
Unlock
()
dr
.
key
=
state
.
key
dr
.
m
.
state
[
dr
.
ck
]
=
state
}
// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
// Instead, it requests a new certificate independently and, upon success,
// replaces dr.m.state item with a new one and updates cache for the given domain.
//
// It may lock and update the Manager.state if the expiration date of the currently
// cached cert is far enough in the future.
//
// The returned value is a time interval after which the renewal should occur again.
func
(
dr
*
domainRenewal
)
do
(
ctx
context
.
Context
)
(
time
.
Duration
,
error
)
{
// a race is likely unavoidable in a distributed environment
// but we try nonetheless
if
tlscert
,
err
:=
dr
.
m
.
cacheGet
(
ctx
,
dr
.
ck
);
err
==
nil
{
next
:=
dr
.
next
(
tlscert
.
Leaf
.
NotAfter
)
if
next
>
dr
.
m
.
renewBefore
()
+
renewJitter
{
signer
,
ok
:=
tlscert
.
PrivateKey
.
(
crypto
.
Signer
)
if
ok
{
state
:=
&
certState
{
key
:
signer
,
cert
:
tlscert
.
Certificate
,
leaf
:
tlscert
.
Leaf
,
}
dr
.
updateState
(
state
)
return
next
,
nil
}
}
}
der
,
leaf
,
err
:=
dr
.
m
.
authorizedCert
(
ctx
,
dr
.
key
,
dr
.
ck
)
if
err
!=
nil
{
return
0
,
err
}
state
:=
&
certState
{
key
:
dr
.
key
,
cert
:
der
,
leaf
:
leaf
,
}
tlscert
,
err
:=
state
.
tlscert
()
if
err
!=
nil
{
return
0
,
err
}
if
err
:=
dr
.
m
.
cachePut
(
ctx
,
dr
.
ck
,
tlscert
);
err
!=
nil
{
return
0
,
err
}
dr
.
updateState
(
state
)
return
dr
.
next
(
leaf
.
NotAfter
),
nil
}
func
(
dr
*
domainRenewal
)
next
(
expiry
time
.
Time
)
time
.
Duration
{
d
:=
expiry
.
Sub
(
timeNow
())
-
dr
.
m
.
renewBefore
()
// add a bit of randomness to renew deadline
n
:=
pseudoRand
.
int63n
(
int64
(
renewJitter
))
d
-=
time
.
Duration
(
n
)
if
d
<
0
{
return
0
}
return
d
}
var
testDidRenewLoop
=
func
(
next
time
.
Duration
,
err
error
)
{}
vendor/golang.org/x/crypto/acme/http.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
acme
import
(
"bytes"
"context"
"crypto"
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"net/http"
"strconv"
"strings"
"time"
)
// retryTimer encapsulates common logic for retrying unsuccessful requests.
// It is not safe for concurrent use.
type
retryTimer
struct
{
// backoffFn provides backoff delay sequence for retries.
// See Client.RetryBackoff doc comment.
backoffFn
func
(
n
int
,
r
*
http
.
Request
,
res
*
http
.
Response
)
time
.
Duration
// n is the current retry attempt.
n
int
}
func
(
t
*
retryTimer
)
inc
()
{
t
.
n
++
}
// backoff pauses the current goroutine as described in Client.RetryBackoff.
func
(
t
*
retryTimer
)
backoff
(
ctx
context
.
Context
,
r
*
http
.
Request
,
res
*
http
.
Response
)
error
{
d
:=
t
.
backoffFn
(
t
.
n
,
r
,
res
)
if
d
<=
0
{
return
fmt
.
Errorf
(
"acme: no more retries for %s; tried %d time(s)"
,
r
.
URL
,
t
.
n
)
}
wakeup
:=
time
.
NewTimer
(
d
)
defer
wakeup
.
Stop
()
select
{
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
case
<-
wakeup
.
C
:
return
nil
}
}
func
(
c
*
Client
)
retryTimer
()
*
retryTimer
{
f
:=
c
.
RetryBackoff
if
f
==
nil
{
f
=
defaultBackoff
}
return
&
retryTimer
{
backoffFn
:
f
}
}
// defaultBackoff provides default Client.RetryBackoff implementation
// using a truncated exponential backoff algorithm,
// as described in Client.RetryBackoff.
//
// The n argument is always bounded between 1 and 30.
// The returned value is always greater than 0.
func
defaultBackoff
(
n
int
,
r
*
http
.
Request
,
res
*
http
.
Response
)
time
.
Duration
{
const
max
=
10
*
time
.
Second
var
jitter
time
.
Duration
if
x
,
err
:=
rand
.
Int
(
rand
.
Reader
,
big
.
NewInt
(
1000
));
err
==
nil
{
// Set the minimum to 1ms to avoid a case where
// an invalid Retry-After value is parsed into 0 below,
// resulting in the 0 returned value which would unintentionally
// stop the retries.
jitter
=
(
1
+
time
.
Duration
(
x
.
Int64
()))
*
time
.
Millisecond
}
if
v
,
ok
:=
res
.
Header
[
"Retry-After"
];
ok
{
return
retryAfter
(
v
[
0
])
+
jitter
}
if
n
<
1
{
n
=
1
}
if
n
>
30
{
n
=
30
}
d
:=
time
.
Duration
(
1
<<
uint
(
n
-
1
))
*
time
.
Second
+
jitter
if
d
>
max
{
return
max
}
return
d
}
// retryAfter parses a Retry-After HTTP header value,
// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
// It returns zero value if v cannot be parsed.
func
retryAfter
(
v
string
)
time
.
Duration
{
if
i
,
err
:=
strconv
.
Atoi
(
v
);
err
==
nil
{
return
time
.
Duration
(
i
)
*
time
.
Second
}
t
,
err
:=
http
.
ParseTime
(
v
)
if
err
!=
nil
{
return
0
}
return
t
.
Sub
(
timeNow
())
}
// resOkay is a function that reports whether the provided response is okay.
// It is expected to keep the response body unread.
type
resOkay
func
(
*
http
.
Response
)
bool
// wantStatus returns a function which reports whether the code
// matches the status code of a response.
func
wantStatus
(
codes
...
int
)
resOkay
{
return
func
(
res
*
http
.
Response
)
bool
{
for
_
,
code
:=
range
codes
{
if
code
==
res
.
StatusCode
{
return
true
}
}
return
false
}
}
// get issues an unsigned GET request to the specified URL.
// It returns a non-error value only when ok reports true.
//
// get retries unsuccessful attempts according to c.RetryBackoff
// until the context is done or a non-retriable error is received.
func
(
c
*
Client
)
get
(
ctx
context
.
Context
,
url
string
,
ok
resOkay
)
(
*
http
.
Response
,
error
)
{
retry
:=
c
.
retryTimer
()
for
{
req
,
err
:=
http
.
NewRequest
(
"GET"
,
url
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
res
,
err
:=
c
.
doNoRetry
(
ctx
,
req
)
switch
{
case
err
!=
nil
:
return
nil
,
err
case
ok
(
res
)
:
return
res
,
nil
case
isRetriable
(
res
.
StatusCode
)
:
retry
.
inc
()
resErr
:=
responseError
(
res
)
res
.
Body
.
Close
()
// Ignore the error value from retry.backoff
// and return the one from last retry, as received from the CA.
if
retry
.
backoff
(
ctx
,
req
,
res
)
!=
nil
{
return
nil
,
resErr
}
default
:
defer
res
.
Body
.
Close
()
return
nil
,
responseError
(
res
)
}
}
}
// post issues a signed POST request in JWS format using the provided key
// to the specified URL.
// It returns a non-error value only when ok reports true.
//
// post retries unsuccessful attempts according to c.RetryBackoff
// until the context is done or a non-retriable error is received.
// It uses postNoRetry to make individual requests.
func
(
c
*
Client
)
post
(
ctx
context
.
Context
,
key
crypto
.
Signer
,
url
string
,
body
interface
{},
ok
resOkay
)
(
*
http
.
Response
,
error
)
{
retry
:=
c
.
retryTimer
()
for
{
res
,
req
,
err
:=
c
.
postNoRetry
(
ctx
,
key
,
url
,
body
)
if
err
!=
nil
{
return
nil
,
err
}
if
ok
(
res
)
{
return
res
,
nil
}
resErr
:=
responseError
(
res
)
res
.
Body
.
Close
()
switch
{
// Check for bad nonce before isRetriable because it may have been returned
// with an unretriable response code such as 400 Bad Request.
case
isBadNonce
(
resErr
)
:
// Consider any previously stored nonce values to be invalid.
c
.
clearNonces
()
case
!
isRetriable
(
res
.
StatusCode
)
:
return
nil
,
resErr
}
retry
.
inc
()
// Ignore the error value from retry.backoff
// and return the one from last retry, as received from the CA.
if
err
:=
retry
.
backoff
(
ctx
,
req
,
res
);
err
!=
nil
{
return
nil
,
resErr
}
}
}
// postNoRetry signs the body with the given key and POSTs it to the provided url.
// The body argument must be JSON-serializable.
// It is used by c.post to retry unsuccessful attempts.
func
(
c
*
Client
)
postNoRetry
(
ctx
context
.
Context
,
key
crypto
.
Signer
,
url
string
,
body
interface
{})
(
*
http
.
Response
,
*
http
.
Request
,
error
)
{
nonce
,
err
:=
c
.
popNonce
(
ctx
,
url
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
b
,
err
:=
jwsEncodeJSON
(
body
,
key
,
nonce
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
req
,
err
:=
http
.
NewRequest
(
"POST"
,
url
,
bytes
.
NewReader
(
b
))
if
err
!=
nil
{
return
nil
,
nil
,
err
}
req
.
Header
.
Set
(
"Content-Type"
,
"application/jose+json"
)
res
,
err
:=
c
.
doNoRetry
(
ctx
,
req
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
c
.
addNonce
(
res
.
Header
)
return
res
,
req
,
nil
}
// doNoRetry issues a request req, replacing its context (if any) with ctx.
func
(
c
*
Client
)
doNoRetry
(
ctx
context
.
Context
,
req
*
http
.
Request
)
(
*
http
.
Response
,
error
)
{
res
,
err
:=
c
.
httpClient
()
.
Do
(
req
.
WithContext
(
ctx
))
if
err
!=
nil
{
select
{
case
<-
ctx
.
Done
()
:
// Prefer the unadorned context error.
// (The acme package had tests assuming this, previously from ctxhttp's
// behavior, predating net/http supporting contexts natively)
// TODO(bradfitz): reconsider this in the future. But for now this
// requires no test updates.
return
nil
,
ctx
.
Err
()
default
:
return
nil
,
err
}
}
return
res
,
nil
}
func
(
c
*
Client
)
httpClient
()
*
http
.
Client
{
if
c
.
HTTPClient
!=
nil
{
return
c
.
HTTPClient
}
return
http
.
DefaultClient
}
// isBadNonce reports whether err is an ACME "badnonce" error.
func
isBadNonce
(
err
error
)
bool
{
// According to the spec badNonce is urn:ietf:params:acme:error:badNonce.
// However, ACME servers in the wild return their versions of the error.
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
// and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66.
ae
,
ok
:=
err
.
(
*
Error
)
return
ok
&&
strings
.
HasSuffix
(
strings
.
ToLower
(
ae
.
ProblemType
),
":badnonce"
)
}
// isRetriable reports whether a request can be retried
// based on the response status code.
//
// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code.
// Callers should parse the response and check with isBadNonce.
func
isRetriable
(
code
int
)
bool
{
return
code
<=
399
||
code
>=
500
||
code
==
http
.
StatusTooManyRequests
}
// responseError creates an error of Error type from resp.
func
responseError
(
resp
*
http
.
Response
)
error
{
// don't care if ReadAll returns an error:
// json.Unmarshal will fail in that case anyway
b
,
_
:=
ioutil
.
ReadAll
(
resp
.
Body
)
e
:=
&
wireError
{
Status
:
resp
.
StatusCode
}
if
err
:=
json
.
Unmarshal
(
b
,
e
);
err
!=
nil
{
// this is not a regular error response:
// populate detail with anything we received,
// e.Status will already contain HTTP response code value
e
.
Detail
=
string
(
b
)
if
e
.
Detail
==
""
{
e
.
Detail
=
resp
.
Status
}
}
return
e
.
error
(
resp
.
Header
)
}
vendor/golang.org/x/crypto/acme/jws.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
acme
import
(
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
_
"crypto/sha512"
// need for EC keys
"encoding/base64"
"encoding/json"
"fmt"
"math/big"
)
// jwsEncodeJSON signs claimset using provided key and a nonce.
// The result is serialized in JSON format.
// See https://tools.ietf.org/html/rfc7515#section-7.
func
jwsEncodeJSON
(
claimset
interface
{},
key
crypto
.
Signer
,
nonce
string
)
([]
byte
,
error
)
{
jwk
,
err
:=
jwkEncode
(
key
.
Public
())
if
err
!=
nil
{
return
nil
,
err
}
alg
,
sha
:=
jwsHasher
(
key
)
if
alg
==
""
||
!
sha
.
Available
()
{
return
nil
,
ErrUnsupportedKey
}
phead
:=
fmt
.
Sprintf
(
`{"alg":%q,"jwk":%s,"nonce":%q}`
,
alg
,
jwk
,
nonce
)
phead
=
base64
.
RawURLEncoding
.
EncodeToString
([]
byte
(
phead
))
cs
,
err
:=
json
.
Marshal
(
claimset
)
if
err
!=
nil
{
return
nil
,
err
}
payload
:=
base64
.
RawURLEncoding
.
EncodeToString
(
cs
)
hash
:=
sha
.
New
()
hash
.
Write
([]
byte
(
phead
+
"."
+
payload
))
sig
,
err
:=
jwsSign
(
key
,
sha
,
hash
.
Sum
(
nil
))
if
err
!=
nil
{
return
nil
,
err
}
enc
:=
struct
{
Protected
string
`json:"protected"`
Payload
string
`json:"payload"`
Sig
string
`json:"signature"`
}{
Protected
:
phead
,
Payload
:
payload
,
Sig
:
base64
.
RawURLEncoding
.
EncodeToString
(
sig
),
}
return
json
.
Marshal
(
&
enc
)
}
// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
// The result is also suitable for creating a JWK thumbprint.
// https://tools.ietf.org/html/rfc7517
func
jwkEncode
(
pub
crypto
.
PublicKey
)
(
string
,
error
)
{
switch
pub
:=
pub
.
(
type
)
{
case
*
rsa
.
PublicKey
:
// https://tools.ietf.org/html/rfc7518#section-6.3.1
n
:=
pub
.
N
e
:=
big
.
NewInt
(
int64
(
pub
.
E
))
// Field order is important.
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
return
fmt
.
Sprintf
(
`{"e":"%s","kty":"RSA","n":"%s"}`
,
base64
.
RawURLEncoding
.
EncodeToString
(
e
.
Bytes
()),
base64
.
RawURLEncoding
.
EncodeToString
(
n
.
Bytes
()),
),
nil
case
*
ecdsa
.
PublicKey
:
// https://tools.ietf.org/html/rfc7518#section-6.2.1
p
:=
pub
.
Curve
.
Params
()
n
:=
p
.
BitSize
/
8
if
p
.
BitSize
%
8
!=
0
{
n
++
}
x
:=
pub
.
X
.
Bytes
()
if
n
>
len
(
x
)
{
x
=
append
(
make
([]
byte
,
n
-
len
(
x
)),
x
...
)
}
y
:=
pub
.
Y
.
Bytes
()
if
n
>
len
(
y
)
{
y
=
append
(
make
([]
byte
,
n
-
len
(
y
)),
y
...
)
}
// Field order is important.
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
return
fmt
.
Sprintf
(
`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
,
p
.
Name
,
base64
.
RawURLEncoding
.
EncodeToString
(
x
),
base64
.
RawURLEncoding
.
EncodeToString
(
y
),
),
nil
}
return
""
,
ErrUnsupportedKey
}
// jwsSign signs the digest using the given key.
// It returns ErrUnsupportedKey if the key type is unknown.
// The hash is used only for RSA keys.
func
jwsSign
(
key
crypto
.
Signer
,
hash
crypto
.
Hash
,
digest
[]
byte
)
([]
byte
,
error
)
{
switch
key
:=
key
.
(
type
)
{
case
*
rsa
.
PrivateKey
:
return
key
.
Sign
(
rand
.
Reader
,
digest
,
hash
)
case
*
ecdsa
.
PrivateKey
:
r
,
s
,
err
:=
ecdsa
.
Sign
(
rand
.
Reader
,
key
,
digest
)
if
err
!=
nil
{
return
nil
,
err
}
rb
,
sb
:=
r
.
Bytes
(),
s
.
Bytes
()
size
:=
key
.
Params
()
.
BitSize
/
8
if
size
%
8
>
0
{
size
++
}
sig
:=
make
([]
byte
,
size
*
2
)
copy
(
sig
[
size
-
len
(
rb
)
:
],
rb
)
copy
(
sig
[
size
*
2
-
len
(
sb
)
:
],
sb
)
return
sig
,
nil
}
return
nil
,
ErrUnsupportedKey
}
// jwsHasher indicates suitable JWS algorithm name and a hash function
// to use for signing a digest with the provided key.
// It returns ("", 0) if the key is not supported.
func
jwsHasher
(
key
crypto
.
Signer
)
(
string
,
crypto
.
Hash
)
{
switch
key
:=
key
.
(
type
)
{
case
*
rsa
.
PrivateKey
:
return
"RS256"
,
crypto
.
SHA256
case
*
ecdsa
.
PrivateKey
:
switch
key
.
Params
()
.
Name
{
case
"P-256"
:
return
"ES256"
,
crypto
.
SHA256
case
"P-384"
:
return
"ES384"
,
crypto
.
SHA384
case
"P-521"
:
return
"ES512"
,
crypto
.
SHA512
}
}
return
""
,
0
}
// JWKThumbprint creates a JWK thumbprint out of pub
// as specified in https://tools.ietf.org/html/rfc7638.
func
JWKThumbprint
(
pub
crypto
.
PublicKey
)
(
string
,
error
)
{
jwk
,
err
:=
jwkEncode
(
pub
)
if
err
!=
nil
{
return
""
,
err
}
b
:=
sha256
.
Sum256
([]
byte
(
jwk
))
return
base64
.
RawURLEncoding
.
EncodeToString
(
b
[
:
]),
nil
}
vendor/golang.org/x/crypto/acme/types.go
deleted
100644 → 0
View file @
2d323373
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
acme
import
(
"crypto"
"crypto/x509"
"errors"
"fmt"
"net/http"
"strings"
"time"
)
// ACME server response statuses used to describe Authorization and Challenge states.
const
(
StatusUnknown
=
"unknown"
StatusPending
=
"pending"
StatusProcessing
=
"processing"
StatusValid
=
"valid"
StatusInvalid
=
"invalid"
StatusRevoked
=
"revoked"
)
// CRLReasonCode identifies the reason for a certificate revocation.
type
CRLReasonCode
int
// CRL reason codes as defined in RFC 5280.
const
(
CRLReasonUnspecified
CRLReasonCode
=
0
CRLReasonKeyCompromise
CRLReasonCode
=
1
CRLReasonCACompromise
CRLReasonCode
=
2
CRLReasonAffiliationChanged
CRLReasonCode
=
3
CRLReasonSuperseded
CRLReasonCode
=
4
CRLReasonCessationOfOperation
CRLReasonCode
=
5
CRLReasonCertificateHold
CRLReasonCode
=
6
CRLReasonRemoveFromCRL
CRLReasonCode
=
8
CRLReasonPrivilegeWithdrawn
CRLReasonCode
=
9
CRLReasonAACompromise
CRLReasonCode
=
10
)
// ErrUnsupportedKey is returned when an unsupported key type is encountered.
var
ErrUnsupportedKey
=
errors
.
New
(
"acme: unknown key type; only RSA and ECDSA are supported"
)
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
type
Error
struct
{
// StatusCode is The HTTP status code generated by the origin server.
StatusCode
int
// ProblemType is a URI reference that identifies the problem type,
// typically in a "urn:acme:error:xxx" form.
ProblemType
string
// Detail is a human-readable explanation specific to this occurrence of the problem.
Detail
string
// Header is the original server error response headers.
// It may be nil.
Header
http
.
Header
}
func
(
e
*
Error
)
Error
()
string
{
return
fmt
.
Sprintf
(
"%d %s: %s"
,
e
.
StatusCode
,
e
.
ProblemType
,
e
.
Detail
)
}
// AuthorizationError indicates that an authorization for an identifier
// did not succeed.
// It contains all errors from Challenge items of the failed Authorization.
type
AuthorizationError
struct
{
// URI uniquely identifies the failed Authorization.
URI
string
// Identifier is an AuthzID.Value of the failed Authorization.
Identifier
string
// Errors is a collection of non-nil error values of Challenge items
// of the failed Authorization.
Errors
[]
error
}
func
(
a
*
AuthorizationError
)
Error
()
string
{
e
:=
make
([]
string
,
len
(
a
.
Errors
))
for
i
,
err
:=
range
a
.
Errors
{
e
[
i
]
=
err
.
Error
()
}
return
fmt
.
Sprintf
(
"acme: authorization error for %s: %s"
,
a
.
Identifier
,
strings
.
Join
(
e
,
"; "
))
}
// RateLimit reports whether err represents a rate limit error and
// any Retry-After duration returned by the server.
//
// See the following for more details on rate limiting:
// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
func
RateLimit
(
err
error
)
(
time
.
Duration
,
bool
)
{
e
,
ok
:=
err
.
(
*
Error
)
if
!
ok
{
return
0
,
false
}
// Some CA implementations may return incorrect values.
// Use case-insensitive comparison.
if
!
strings
.
HasSuffix
(
strings
.
ToLower
(
e
.
ProblemType
),
":ratelimited"
)
{
return
0
,
false
}
if
e
.
Header
==
nil
{
return
0
,
true
}
return
retryAfter
(
e
.
Header
.
Get
(
"Retry-After"
)),
true
}
// Account is a user account. It is associated with a private key.
type
Account
struct
{
// URI is the account unique ID, which is also a URL used to retrieve
// account data from the CA.
URI
string
// Contact is a slice of contact info used during registration.
Contact
[]
string
// The terms user has agreed to.
// A value not matching CurrentTerms indicates that the user hasn't agreed
// to the actual Terms of Service of the CA.
AgreedTerms
string
// Actual terms of a CA.
CurrentTerms
string
// Authz is the authorization URL used to initiate a new authz flow.
Authz
string
// Authorizations is a URI from which a list of authorizations
// granted to this account can be fetched via a GET request.
Authorizations
string
// Certificates is a URI from which a list of certificates
// issued for this account can be fetched via a GET request.
Certificates
string
}
// Directory is ACME server discovery data.
type
Directory
struct
{
// RegURL is an account endpoint URL, allowing for creating new
// and modifying existing accounts.
RegURL
string
// AuthzURL is used to initiate Identifier Authorization flow.
AuthzURL
string
// CertURL is a new certificate issuance endpoint URL.
CertURL
string
// RevokeURL is used to initiate a certificate revocation flow.
RevokeURL
string
// Term is a URI identifying the current terms of service.
Terms
string
// Website is an HTTP or HTTPS URL locating a website
// providing more information about the ACME server.
Website
string
// CAA consists of lowercase hostname elements, which the ACME server
// recognises as referring to itself for the purposes of CAA record validation
// as defined in RFC6844.
CAA
[]
string
}
// Challenge encodes a returned CA challenge.
// Its Error field may be non-nil if the challenge is part of an Authorization
// with StatusInvalid.
type
Challenge
struct
{
// Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
Type
string
// URI is where a challenge response can be posted to.
URI
string
// Token is a random value that uniquely identifies the challenge.
Token
string
// Status identifies the status of this challenge.
Status
string
// Error indicates the reason for an authorization failure
// when this challenge was used.
// The type of a non-nil value is *Error.
Error
error
}
// Authorization encodes an authorization response.
type
Authorization
struct
{
// URI uniquely identifies a authorization.
URI
string
// Status identifies the status of an authorization.
Status
string
// Identifier is what the account is authorized to represent.
Identifier
AuthzID
// Challenges that the client needs to fulfill in order to prove possession
// of the identifier (for pending authorizations).
// For final authorizations, the challenges that were used.
Challenges
[]
*
Challenge
// A collection of sets of challenges, each of which would be sufficient
// to prove possession of the identifier.
// Clients must complete a set of challenges that covers at least one set.
// Challenges are identified by their indices in the challenges array.
// If this field is empty, the client needs to complete all challenges.
Combinations
[][]
int
}
// AuthzID is an identifier that an account is authorized to represent.
type
AuthzID
struct
{
Type
string
// The type of identifier, e.g. "dns".
Value
string
// The identifier itself, e.g. "example.org".
}
// wireAuthz is ACME JSON representation of Authorization objects.
type
wireAuthz
struct
{
Status
string
Challenges
[]
wireChallenge
Combinations
[][]
int
Identifier
struct
{
Type
string
Value
string
}
}
func
(
z
*
wireAuthz
)
authorization
(
uri
string
)
*
Authorization
{
a
:=
&
Authorization
{
URI
:
uri
,
Status
:
z
.
Status
,
Identifier
:
AuthzID
{
Type
:
z
.
Identifier
.
Type
,
Value
:
z
.
Identifier
.
Value
},
Combinations
:
z
.
Combinations
,
// shallow copy
Challenges
:
make
([]
*
Challenge
,
len
(
z
.
Challenges
)),
}
for
i
,
v
:=
range
z
.
Challenges
{
a
.
Challenges
[
i
]
=
v
.
challenge
()
}
return
a
}
func
(
z
*
wireAuthz
)
error
(
uri
string
)
*
AuthorizationError
{
err
:=
&
AuthorizationError
{
URI
:
uri
,
Identifier
:
z
.
Identifier
.
Value
,
}
for
_
,
raw
:=
range
z
.
Challenges
{
if
raw
.
Error
!=
nil
{
err
.
Errors
=
append
(
err
.
Errors
,
raw
.
Error
.
error
(
nil
))
}
}
return
err
}
// wireChallenge is ACME JSON challenge representation.
type
wireChallenge
struct
{
URI
string
`json:"uri"`
Type
string
Token
string
Status
string
Error
*
wireError
}
func
(
c
*
wireChallenge
)
challenge
()
*
Challenge
{
v
:=
&
Challenge
{
URI
:
c
.
URI
,
Type
:
c
.
Type
,
Token
:
c
.
Token
,
Status
:
c
.
Status
,
}
if
v
.
Status
==
""
{
v
.
Status
=
StatusPending
}
if
c
.
Error
!=
nil
{
v
.
Error
=
c
.
Error
.
error
(
nil
)
}
return
v
}
// wireError is a subset of fields of the Problem Details object
// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
type
wireError
struct
{
Status
int
Type
string
Detail
string
}
func
(
e
*
wireError
)
error
(
h
http
.
Header
)
*
Error
{
return
&
Error
{
StatusCode
:
e
.
Status
,
ProblemType
:
e
.
Type
,
Detail
:
e
.
Detail
,
Header
:
h
,
}
}
// CertOption is an optional argument type for the TLS ChallengeCert methods for
// customizing a temporary certificate for TLS-based challenges.
type
CertOption
interface
{
privateCertOpt
()
}
// WithKey creates an option holding a private/public key pair.
// The private part signs a certificate, and the public part represents the signee.
func
WithKey
(
key
crypto
.
Signer
)
CertOption
{
return
&
certOptKey
{
key
}
}
type
certOptKey
struct
{
key
crypto
.
Signer
}
func
(
*
certOptKey
)
privateCertOpt
()
{}
// WithTemplate creates an option for specifying a certificate template.
// See x509.CreateCertificate for template usage details.
//
// In TLS ChallengeCert methods, the template is also used as parent,
// resulting in a self-signed certificate.
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
func
WithTemplate
(
t
*
x509
.
Certificate
)
CertOption
{
return
(
*
certOptTemplate
)(
t
)
}
type
certOptTemplate
x509
.
Certificate
func
(
*
certOptTemplate
)
privateCertOpt
()
{}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment