Migrate to go-acme/lego.
This commit is contained in:
parent
4a68d29ce2
commit
87da7520de
286 changed files with 14021 additions and 2501 deletions
269
vendor/github.com/oracle/oci-go-sdk/common/http_signer.go
generated
vendored
Normal file
269
vendor/github.com/oracle/oci-go-sdk/common/http_signer.go
generated
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HTTPRequestSigner the interface to sign a request
|
||||
type HTTPRequestSigner interface {
|
||||
Sign(r *http.Request) error
|
||||
}
|
||||
|
||||
// KeyProvider interface that wraps information about the key's account owner
|
||||
type KeyProvider interface {
|
||||
PrivateRSAKey() (*rsa.PrivateKey, error)
|
||||
KeyID() (string, error)
|
||||
}
|
||||
|
||||
const signerVersion = "1"
|
||||
|
||||
// SignerBodyHashPredicate a function that allows to disable/enable body hashing
|
||||
// of requests and headers associated with body content
|
||||
type SignerBodyHashPredicate func(r *http.Request) bool
|
||||
|
||||
// ociRequestSigner implements the http-signatures-draft spec
|
||||
// as described in https://tools.ietf.org/html/draft-cavage-http-signatures-08
|
||||
type ociRequestSigner struct {
|
||||
KeyProvider KeyProvider
|
||||
GenericHeaders []string
|
||||
BodyHeaders []string
|
||||
ShouldHashBody SignerBodyHashPredicate
|
||||
}
|
||||
|
||||
var (
|
||||
defaultGenericHeaders = []string{"date", "(request-target)", "host"}
|
||||
defaultBodyHeaders = []string{"content-length", "content-type", "x-content-sha256"}
|
||||
defaultBodyHashPredicate = func(r *http.Request) bool {
|
||||
return r.Method == http.MethodPost || r.Method == http.MethodPut || r.Method == http.MethodPatch
|
||||
}
|
||||
)
|
||||
|
||||
// DefaultGenericHeaders list of default generic headers that is used in signing
|
||||
func DefaultGenericHeaders() []string {
|
||||
return makeACopy(defaultGenericHeaders)
|
||||
}
|
||||
|
||||
// DefaultBodyHeaders list of default body headers that is used in signing
|
||||
func DefaultBodyHeaders() []string {
|
||||
return makeACopy(defaultBodyHeaders)
|
||||
}
|
||||
|
||||
// DefaultRequestSigner creates a signer with default parameters.
|
||||
func DefaultRequestSigner(provider KeyProvider) HTTPRequestSigner {
|
||||
return RequestSigner(provider, defaultGenericHeaders, defaultBodyHeaders)
|
||||
}
|
||||
|
||||
// RequestSignerExcludeBody creates a signer without hash the body.
|
||||
func RequestSignerExcludeBody(provider KeyProvider) HTTPRequestSigner {
|
||||
bodyHashPredicate := func(r *http.Request) bool {
|
||||
// week request signer will not hash the body
|
||||
return false
|
||||
}
|
||||
return RequestSignerWithBodyHashingPredicate(provider, defaultGenericHeaders, defaultBodyHeaders, bodyHashPredicate)
|
||||
}
|
||||
|
||||
// NewSignerFromOCIRequestSigner creates a copy of the request signer and attaches the new SignerBodyHashPredicate
|
||||
// returns an error if the passed signer is not of type ociRequestSigner
|
||||
func NewSignerFromOCIRequestSigner(oldSigner HTTPRequestSigner, predicate SignerBodyHashPredicate) (HTTPRequestSigner, error) {
|
||||
if oldS, ok := oldSigner.(ociRequestSigner); ok {
|
||||
s := ociRequestSigner{
|
||||
KeyProvider: oldS.KeyProvider,
|
||||
GenericHeaders: oldS.GenericHeaders,
|
||||
BodyHeaders: oldS.BodyHeaders,
|
||||
ShouldHashBody: predicate,
|
||||
}
|
||||
return s, nil
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("can not create a signer, input signer needs to be of type ociRequestSigner")
|
||||
}
|
||||
|
||||
// RequestSigner creates a signer that utilizes the specified headers for signing
|
||||
// and the default predicate for using the body of the request as part of the signature
|
||||
func RequestSigner(provider KeyProvider, genericHeaders, bodyHeaders []string) HTTPRequestSigner {
|
||||
return ociRequestSigner{
|
||||
KeyProvider: provider,
|
||||
GenericHeaders: genericHeaders,
|
||||
BodyHeaders: bodyHeaders,
|
||||
ShouldHashBody: defaultBodyHashPredicate}
|
||||
}
|
||||
|
||||
// RequestSignerWithBodyHashingPredicate creates a signer that utilizes the specified headers for signing, as well as a predicate for using
|
||||
// the body of the request and bodyHeaders parameter as part of the signature
|
||||
func RequestSignerWithBodyHashingPredicate(provider KeyProvider, genericHeaders, bodyHeaders []string, shouldHashBody SignerBodyHashPredicate) HTTPRequestSigner {
|
||||
return ociRequestSigner{
|
||||
KeyProvider: provider,
|
||||
GenericHeaders: genericHeaders,
|
||||
BodyHeaders: bodyHeaders,
|
||||
ShouldHashBody: shouldHashBody}
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) getSigningHeaders(r *http.Request) []string {
|
||||
var result []string
|
||||
result = append(result, signer.GenericHeaders...)
|
||||
|
||||
if signer.ShouldHashBody(r) {
|
||||
result = append(result, signer.BodyHeaders...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) getSigningString(request *http.Request) string {
|
||||
signingHeaders := signer.getSigningHeaders(request)
|
||||
signingParts := make([]string, len(signingHeaders))
|
||||
for i, part := range signingHeaders {
|
||||
var value string
|
||||
part = strings.ToLower(part)
|
||||
switch part {
|
||||
case "(request-target)":
|
||||
value = getRequestTarget(request)
|
||||
case "host":
|
||||
value = request.URL.Host
|
||||
if len(value) == 0 {
|
||||
value = request.Host
|
||||
}
|
||||
default:
|
||||
value = request.Header.Get(part)
|
||||
}
|
||||
signingParts[i] = fmt.Sprintf("%s: %s", part, value)
|
||||
}
|
||||
|
||||
signingString := strings.Join(signingParts, "\n")
|
||||
return signingString
|
||||
|
||||
}
|
||||
|
||||
func getRequestTarget(request *http.Request) string {
|
||||
lowercaseMethod := strings.ToLower(request.Method)
|
||||
return fmt.Sprintf("%s %s", lowercaseMethod, request.URL.RequestURI())
|
||||
}
|
||||
|
||||
func calculateHashOfBody(request *http.Request) (err error) {
|
||||
var hash string
|
||||
hash, err = GetBodyHash(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
request.Header.Set(requestHeaderXContentSHA256, hash)
|
||||
return
|
||||
}
|
||||
|
||||
// drainBody reads all of b to memory and then returns two equivalent
|
||||
// ReadClosers yielding the same bytes.
|
||||
//
|
||||
// It returns an error if the initial slurp of all bytes fails. It does not attempt
|
||||
// to make the returned ReadClosers have identical error-matching behavior.
|
||||
func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
|
||||
if b == http.NoBody {
|
||||
// No copying needed. Preserve the magic sentinel meaning of NoBody.
|
||||
return http.NoBody, http.NoBody, nil
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if _, err = buf.ReadFrom(b); err != nil {
|
||||
return nil, b, err
|
||||
}
|
||||
if err = b.Close(); err != nil {
|
||||
return nil, b, err
|
||||
}
|
||||
return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
|
||||
}
|
||||
|
||||
func hashAndEncode(data []byte) string {
|
||||
hashedContent := sha256.Sum256(data)
|
||||
hash := base64.StdEncoding.EncodeToString(hashedContent[:])
|
||||
return hash
|
||||
}
|
||||
|
||||
// GetBodyHash creates a base64 string from the hash of body the request
|
||||
func GetBodyHash(request *http.Request) (hashString string, err error) {
|
||||
if request.Body == nil {
|
||||
request.ContentLength = 0
|
||||
request.Header.Set(requestHeaderContentLength, fmt.Sprintf("%v", request.ContentLength))
|
||||
return hashAndEncode([]byte("")), nil
|
||||
}
|
||||
|
||||
var data []byte
|
||||
bReader := request.Body
|
||||
bReader, request.Body, err = drainBody(request.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
|
||||
}
|
||||
|
||||
data, err = ioutil.ReadAll(bReader)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
|
||||
}
|
||||
|
||||
// Since the request can be coming from a binary body. Make an attempt to set the body length
|
||||
request.ContentLength = int64(len(data))
|
||||
request.Header.Set(requestHeaderContentLength, fmt.Sprintf("%v", request.ContentLength))
|
||||
|
||||
hashString = hashAndEncode(data)
|
||||
return
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) computeSignature(request *http.Request) (signature string, err error) {
|
||||
signingString := signer.getSigningString(request)
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
privateKey, err := signer.KeyProvider.PrivateRSAKey()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var unencodedSig []byte
|
||||
unencodedSig, e := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
|
||||
if e != nil {
|
||||
err = fmt.Errorf("can not compute signature while signing the request %s: ", e.Error())
|
||||
return
|
||||
}
|
||||
|
||||
signature = base64.StdEncoding.EncodeToString(unencodedSig)
|
||||
return
|
||||
}
|
||||
|
||||
// Sign signs the http request, by inspecting the necessary headers. Once signed
|
||||
// the request will have the proper 'Authorization' header set, otherwise
|
||||
// and error is returned
|
||||
func (signer ociRequestSigner) Sign(request *http.Request) (err error) {
|
||||
if signer.ShouldHashBody(request) {
|
||||
err = calculateHashOfBody(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var signature string
|
||||
if signature, err = signer.computeSignature(request); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signingHeaders := strings.Join(signer.getSigningHeaders(request), " ")
|
||||
|
||||
var keyID string
|
||||
if keyID, err = signer.KeyProvider.KeyID(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
authValue := fmt.Sprintf("Signature version=\"%s\",headers=\"%s\",keyId=\"%s\",algorithm=\"rsa-sha256\",signature=\"%s\"",
|
||||
signerVersion, signingHeaders, keyID, signature)
|
||||
|
||||
request.Header.Set(requestHeaderAuthorization, authValue)
|
||||
|
||||
return
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue