garm/vendor/github.com/go-macaroon-bakery/macaroon-bakery/v3/httpbakery/keyring.go
Gabriel Adrian Samfira c61b7fd268
Update go modules
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2023-03-12 16:22:37 +02:00

113 lines
3.7 KiB
Go

package httpbakery
import (
"context"
"net/http"
"net/url"
"gopkg.in/errgo.v1"
"gopkg.in/httprequest.v1"
"github.com/go-macaroon-bakery/macaroon-bakery/v3/bakery"
)
var _ bakery.ThirdPartyLocator = (*ThirdPartyLocator)(nil)
// NewThirdPartyLocator returns a new third party
// locator that uses the given client to find
// information about third parties and
// uses the given cache as a backing.
//
// If cache is nil, a new cache will be created.
//
// If client is nil, http.DefaultClient will be used.
func NewThirdPartyLocator(client httprequest.Doer, cache *bakery.ThirdPartyStore) *ThirdPartyLocator {
if cache == nil {
cache = bakery.NewThirdPartyStore()
}
if client == nil {
client = http.DefaultClient
}
return &ThirdPartyLocator{
client: client,
cache: cache,
}
}
// AllowInsecureThirdPartyLocator holds whether ThirdPartyLocator allows
// insecure HTTP connections for fetching third party information.
// It is provided for testing purposes and should not be used
// in production code.
var AllowInsecureThirdPartyLocator = false
// ThirdPartyLocator represents locator that can interrogate
// third party discharge services for information. By default it refuses
// to use insecure URLs.
type ThirdPartyLocator struct {
client httprequest.Doer
allowInsecure bool
cache *bakery.ThirdPartyStore
}
// AllowInsecure allows insecure URLs. This can be useful
// for testing purposes. See also AllowInsecureThirdPartyLocator.
func (kr *ThirdPartyLocator) AllowInsecure() {
kr.allowInsecure = true
}
// ThirdPartyLocator implements bakery.ThirdPartyLocator
// by first looking in the backing cache and, if that fails,
// making an HTTP request to find the information associated
// with the given discharge location.
//
// It refuses to fetch information from non-HTTPS URLs.
func (kr *ThirdPartyLocator) ThirdPartyInfo(ctx context.Context, loc string) (bakery.ThirdPartyInfo, error) {
// If the cache has an entry in, we can use it regardless of URL scheme.
// This allows entries for notionally insecure URLs to be added by other means (for
// example via a config file).
info, err := kr.cache.ThirdPartyInfo(ctx, loc)
if err == nil {
return info, nil
}
u, err := url.Parse(loc)
if err != nil {
return bakery.ThirdPartyInfo{}, errgo.Notef(err, "invalid discharge URL %q", loc)
}
if u.Scheme != "https" && !kr.allowInsecure && !AllowInsecureThirdPartyLocator {
return bakery.ThirdPartyInfo{}, errgo.Newf("untrusted discharge URL %q", loc)
}
info, err = ThirdPartyInfoForLocation(ctx, kr.client, loc)
if err != nil {
return bakery.ThirdPartyInfo{}, errgo.Mask(err)
}
kr.cache.AddInfo(loc, info)
return info, nil
}
// ThirdPartyInfoForLocation returns information on the third party
// discharge server running at the given location URL. Note that this is
// insecure if an http: URL scheme is used. If client is nil,
// http.DefaultClient will be used.
func ThirdPartyInfoForLocation(ctx context.Context, client httprequest.Doer, url string) (bakery.ThirdPartyInfo, error) {
dclient := newDischargeClient(url, client)
info, err := dclient.DischargeInfo(ctx, &dischargeInfoRequest{})
if err == nil {
return bakery.ThirdPartyInfo{
PublicKey: *info.PublicKey,
Version: info.Version,
}, nil
}
derr, ok := errgo.Cause(err).(*httprequest.DecodeResponseError)
if !ok || derr.Response.StatusCode != http.StatusNotFound {
return bakery.ThirdPartyInfo{}, errgo.Mask(err)
}
// The new endpoint isn't there, so try the old one.
pkResp, err := dclient.PublicKey(ctx, &publicKeyRequest{})
if err != nil {
return bakery.ThirdPartyInfo{}, errgo.Mask(err)
}
return bakery.ThirdPartyInfo{
PublicKey: *pkResp.PublicKey,
Version: bakery.Version1,
}, nil
}