github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/azure/internal/azureauth/discovery.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azureauth 5 6 import ( 7 "net/http" 8 "net/url" 9 "regexp" 10 "strings" 11 12 "github.com/Azure/azure-sdk-for-go/arm/resources/subscriptions" 13 "github.com/juju/errors" 14 "github.com/juju/utils" 15 ) 16 17 const authenticateHeaderKey = "WWW-Authenticate" 18 19 var authorizationUriRegexp = regexp.MustCompile(`authorization_uri="([^"]*)"`) 20 21 // DiscoverAuthorizationID returns the OAuth authorization URI for the given 22 // subscription ID. This can be used to determine the AD tenant ID. 23 func DiscoverAuthorizationURI(client subscriptions.Client, subscriptionID string) (*url.URL, error) { 24 // We make an unauthenticated request to the Azure API, which 25 // responds with the authentication URL with the tenant ID in it. 26 result, err := client.Get(subscriptionID) 27 if err == nil { 28 return nil, errors.New("expected unauthorized error response") 29 } 30 if result.Response.Response == nil { 31 return nil, errors.Trace(err) 32 } 33 if result.StatusCode != http.StatusUnauthorized { 34 return nil, errors.Annotatef(err, "expected unauthorized error response, got %v", result.StatusCode) 35 } 36 37 header := result.Header.Get(authenticateHeaderKey) 38 if header == "" { 39 return nil, errors.Errorf("%s header not found", authenticateHeaderKey) 40 } 41 match := authorizationUriRegexp.FindStringSubmatch(header) 42 if match == nil { 43 return nil, errors.Errorf( 44 "authorization_uri not found in %s header (%q)", 45 authenticateHeaderKey, header, 46 ) 47 } 48 return url.Parse(match[1]) 49 } 50 51 // AuthorizationURITenantID returns the tenant ID portion of the given URL, 52 // which is expected to have come from DiscoverAuthorizationURI. 53 func AuthorizationURITenantID(url *url.URL) (string, error) { 54 path := strings.TrimPrefix(url.Path, "/") 55 if _, err := utils.UUIDFromString(path); err != nil { 56 return "", errors.NotValidf("authorization_uri %q", url) 57 } 58 return path, nil 59 }