1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
package client
import (
"crypto/tls"
"errors"
"net/http"
"net/url"
"strings"
"time"
"github.com/cloudflare/cfssl/auth"
"github.com/cloudflare/cfssl/info"
)
// Strategy is the means by which the server to use as a remote should
// be selected.
type Strategy int
const (
// StrategyInvalid indicates any strategy that is unsupported
// or returned when no strategy is applicable.
StrategyInvalid = iota
// StrategyOrderedList is a sequential list of servers: if the
// first server cannot be reached, the next is used. The
// client will proceed in this manner until the list of
// servers is exhausted, and then an error is returned.
StrategyOrderedList
)
var strategyStrings = map[string]Strategy{
"ordered_list": StrategyOrderedList,
}
// StrategyFromString takes a string describing a
func StrategyFromString(s string) Strategy {
s = strings.TrimSpace(strings.ToLower(s))
strategy, ok := strategyStrings[s]
if !ok {
return StrategyInvalid
}
return strategy
}
// NewGroup will use the collection of remotes specified with the
// given strategy.
func NewGroup(remotes []string, tlsConfig *tls.Config, strategy Strategy) (Remote, error) {
var servers = make([]*server, len(remotes))
for i := range remotes {
u, err := normalizeURL(remotes[i])
if err != nil {
return nil, err
}
servers[i] = newServer(u, tlsConfig)
}
switch strategy {
case StrategyOrderedList:
return newOrdererdListGroup(servers)
default:
return nil, errors.New("unrecognised strategy")
}
}
type orderedListGroup struct {
remotes []*server
}
func (g *orderedListGroup) Hosts() []string {
var hosts = make([]string, 0, len(g.remotes))
for _, srv := range g.remotes {
srvHosts := srv.Hosts()
hosts = append(hosts, srvHosts[0])
}
return hosts
}
func (g *orderedListGroup) SetRequestTimeout(timeout time.Duration) {
for _, srv := range g.remotes {
srv.SetRequestTimeout(timeout)
}
}
func (g *orderedListGroup) SetProxy(proxy func(*http.Request) (*url.URL, error)) {
for _, srv := range g.remotes {
srv.SetProxy(proxy)
}
}
func newOrdererdListGroup(remotes []*server) (Remote, error) {
return &orderedListGroup{
remotes: remotes,
}, nil
}
func (g *orderedListGroup) AuthSign(req, id []byte, provider auth.Provider) (resp []byte, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].AuthSign(req, id, provider)
if err == nil {
return resp, nil
}
}
return nil, err
}
func (g *orderedListGroup) Sign(jsonData []byte) (resp []byte, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].Sign(jsonData)
if err == nil {
return resp, nil
}
}
return nil, err
}
func (g *orderedListGroup) Info(jsonData []byte) (resp *info.Resp, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].Info(jsonData)
if err == nil {
return resp, nil
}
}
return nil, err
}
// SetReqModifier does nothing because there is no request modifier for group
func (g *orderedListGroup) SetReqModifier(mod func(*http.Request, []byte)) {
// noop
}
|