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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
package disco
import (
"fmt"
"net/url"
"strings"
"golang.org/x/oauth2"
)
// OAuthClient represents an OAuth client configuration, which is used for
// unusual services that require an entire OAuth client configuration as part
// of their service discovery, rather than just a URL.
type OAuthClient struct {
// ID is the identifier for the client, to be used as "client_id" in
// OAuth requests.
ID string
// Authorization URL is the URL of the authorization endpoint that must
// be used for this OAuth client, as defined in the OAuth2 specifications.
//
// Not all grant types use the authorization endpoint, so it may be omitted
// if none of the grant types in SupportedGrantTypes require it.
AuthorizationURL *url.URL
// Token URL is the URL of the token endpoint that must be used for this
// OAuth client, as defined in the OAuth2 specifications.
//
// Not all grant types use the token endpoint, so it may be omitted
// if none of the grant types in SupportedGrantTypes require it.
TokenURL *url.URL
// MinPort and MaxPort define a range of TCP ports on localhost that this
// client is able to use as redirect_uri in an authorization request.
// Terraform will select a port from this range for the temporary HTTP
// server it creates to receive the authorization response, giving
// a URL like http://localhost:NNN/ where NNN is the selected port number.
//
// Terraform will reject any port numbers in this range less than 1024,
// to respect the common convention (enforced on some operating systems)
// that lower port numbers are reserved for "privileged" services.
MinPort, MaxPort uint16
// SupportedGrantTypes is a set of the grant types that the client may
// choose from. This includes an entry for each distinct type advertised
// by the server, even if a particular keyword is not supported by the
// current version of Terraform.
SupportedGrantTypes OAuthGrantTypeSet
// Oauth2 does not require scopes for the authorization endpoint, however
// OIDC does. Optional list of scopes to include in auth code and token
// requests.
Scopes []string
}
// Endpoint returns an oauth2.Endpoint value ready to be used with the oauth2
// library, representing the URLs from the receiver.
func (c *OAuthClient) Endpoint() oauth2.Endpoint {
ep := oauth2.Endpoint{
// We don't actually auth because we're not a server-based OAuth client,
// so this instead just means that we include client_id as an argument
// in our requests.
AuthStyle: oauth2.AuthStyleInParams,
}
if c.AuthorizationURL != nil {
ep.AuthURL = c.AuthorizationURL.String()
}
if c.TokenURL != nil {
ep.TokenURL = c.TokenURL.String()
}
return ep
}
// OAuthGrantType is an enumeration of grant type strings that a host can
// advertise support for.
//
// Values of this type don't necessarily match with a known constant of the
// type, because they may represent grant type keywords defined in a later
// version of Terraform which this version doesn't yet know about.
type OAuthGrantType string
const (
// OAuthAuthzCodeGrant represents an authorization code grant, as
// defined in IETF RFC 6749 section 4.1.
OAuthAuthzCodeGrant = OAuthGrantType("authz_code")
// OAuthOwnerPasswordGrant represents a resource owner password
// credentials grant, as defined in IETF RFC 6749 section 4.3.
OAuthOwnerPasswordGrant = OAuthGrantType("password")
)
// UsesAuthorizationEndpoint returns true if the receiving grant type makes
// use of the authorization endpoint from the client configuration, and thus
// if the authorization endpoint ought to be required.
func (t OAuthGrantType) UsesAuthorizationEndpoint() bool {
switch t {
case OAuthAuthzCodeGrant:
return true
case OAuthOwnerPasswordGrant:
return false
default:
// We'll default to false so that we don't impose any requirements
// on any grant type keywords that might be defined for future
// versions of Terraform.
return false
}
}
// UsesTokenEndpoint returns true if the receiving grant type makes
// use of the token endpoint from the client configuration, and thus
// if the authorization endpoint ought to be required.
func (t OAuthGrantType) UsesTokenEndpoint() bool {
switch t {
case OAuthAuthzCodeGrant:
return true
case OAuthOwnerPasswordGrant:
return true
default:
// We'll default to false so that we don't impose any requirements
// on any grant type keywords that might be defined for future
// versions of Terraform.
return false
}
}
// OAuthGrantTypeSet represents a set of OAuthGrantType values.
type OAuthGrantTypeSet map[OAuthGrantType]struct{}
// NewOAuthGrantTypeSet constructs a new grant type set from the given list
// of grant type keyword strings. Any duplicates in the list are ignored.
func NewOAuthGrantTypeSet(keywords ...string) OAuthGrantTypeSet {
ret := make(OAuthGrantTypeSet, len(keywords))
for _, kw := range keywords {
ret[OAuthGrantType(kw)] = struct{}{}
}
return ret
}
// Has returns true if the given grant type is in the receiving set.
func (s OAuthGrantTypeSet) Has(t OAuthGrantType) bool {
_, ok := s[t]
return ok
}
// RequiresAuthorizationEndpoint returns true if any of the grant types in
// the set are known to require an authorization endpoint.
func (s OAuthGrantTypeSet) RequiresAuthorizationEndpoint() bool {
for t := range s {
if t.UsesAuthorizationEndpoint() {
return true
}
}
return false
}
// RequiresTokenEndpoint returns true if any of the grant types in
// the set are known to require a token endpoint.
func (s OAuthGrantTypeSet) RequiresTokenEndpoint() bool {
for t := range s {
if t.UsesTokenEndpoint() {
return true
}
}
return false
}
// GoString implements fmt.GoStringer.
func (s OAuthGrantTypeSet) GoString() string {
var buf strings.Builder
i := 0
buf.WriteString("disco.NewOAuthGrantTypeSet(")
for t := range s {
if i > 0 {
buf.WriteString(", ")
}
fmt.Fprintf(&buf, "%q", string(t))
i++
}
buf.WriteString(")")
return buf.String()
}
|