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  }