|
|
|
|
@ -41,10 +41,9 @@ var (
|
|
|
|
|
|
|
|
|
|
// Authenticate fetches a token from the local file cache or initiates a consent
|
|
|
|
|
// flow and waits for token to be obtained.
|
|
|
|
|
func Authenticate(env azure.Environment, tenantID string, say func(string), apiScope string) (*adal.ServicePrincipalToken, error) {
|
|
|
|
|
func Authenticate(env azure.Environment, tenantID string, say func(string), scope string) (*adal.ServicePrincipalToken, error) {
|
|
|
|
|
clientID, ok := clientIDs[env.Name]
|
|
|
|
|
var resourceid string
|
|
|
|
|
var endpoint string
|
|
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("packer-azure application not set up for Azure environment %q", env.Name)
|
|
|
|
|
@ -57,14 +56,11 @@ func Authenticate(env azure.Environment, tenantID string, say func(string), apiS
|
|
|
|
|
|
|
|
|
|
// for AzurePublicCloud (https://management.core.windows.net/), this old
|
|
|
|
|
// Service Management scope covers both ASM and ARM.
|
|
|
|
|
//apiScope := env.ServiceManagementEndpoint
|
|
|
|
|
|
|
|
|
|
if strings.Contains(apiScope, "vault") {
|
|
|
|
|
if strings.Contains(scope, "vault") {
|
|
|
|
|
resourceid = "vault"
|
|
|
|
|
endpoint = env.KeyVaultEndpoint
|
|
|
|
|
} else {
|
|
|
|
|
resourceid = "mgmt"
|
|
|
|
|
endpoint = env.ResourceManagerEndpoint
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tokenPath := tokenCachePath(tenantID + resourceid)
|
|
|
|
|
@ -75,41 +71,18 @@ func Authenticate(env azure.Environment, tenantID string, say func(string), apiS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lookup the token cache file for an existing token.
|
|
|
|
|
spt, err := tokenFromFile(say, *oauthCfg, tokenPath, clientID, apiScope, saveTokenCallback)
|
|
|
|
|
spt, err := tokenFromFile(say, *oauthCfg, tokenPath, clientID, scope, saveTokenCallback)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if spt != nil {
|
|
|
|
|
say(fmt.Sprintf("Auth token found in file: %s", tokenPath))
|
|
|
|
|
|
|
|
|
|
// NOTE(ahmetalpbalkan): The token file we found may contain an
|
|
|
|
|
// expired access_token. In that case, the first call to Azure SDK will
|
|
|
|
|
// attempt to refresh the token using refresh_token, which might have
|
|
|
|
|
// expired[1], in that case we will get an error and we shall remove the
|
|
|
|
|
// token file and initiate token flow again so that the user would not
|
|
|
|
|
// need removing the token cache file manually.
|
|
|
|
|
//
|
|
|
|
|
// [1]: expiration date of refresh_token is not returned in AAD /token
|
|
|
|
|
// response, we just know it is 14 days. Therefore user’s token
|
|
|
|
|
// will go stale every 14 days and we will delete the token file,
|
|
|
|
|
// re-initiate the device flow.
|
|
|
|
|
say("Validating the token.")
|
|
|
|
|
if err = validateToken(endpoint, spt); err != nil {
|
|
|
|
|
say(fmt.Sprintf("Error: %v", err))
|
|
|
|
|
say("Stored Azure credentials expired. Please reauthenticate.")
|
|
|
|
|
say(fmt.Sprintf("Deleting %s", tokenPath))
|
|
|
|
|
if err := os.RemoveAll(tokenPath); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("Error deleting stale token file: %v", err)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
say("Token works.")
|
|
|
|
|
return spt, nil
|
|
|
|
|
}
|
|
|
|
|
return spt, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start an OAuth 2.0 device flow
|
|
|
|
|
say(fmt.Sprintf("Initiating device flow: %s", tokenPath))
|
|
|
|
|
spt, err = tokenFromDeviceFlow(say, *oauthCfg, clientID, apiScope)
|
|
|
|
|
spt, err = tokenFromDeviceFlow(say, *oauthCfg, clientID, scope)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
@ -195,19 +168,6 @@ func mkTokenCallback(path string) adal.TokenRefreshCallback {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// validateToken makes a call to Azure SDK with given token, essentially making
|
|
|
|
|
// sure if the access_token valid, if not it uses SDK’s functionality to
|
|
|
|
|
// automatically refresh the token using refresh_token (which might have
|
|
|
|
|
// expired). This check is essentially to make sure refresh_token is good.
|
|
|
|
|
func validateToken(env string, token *adal.ServicePrincipalToken) error {
|
|
|
|
|
err := token.EnsureFresh()
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("%s token validity check failed: %v", env, err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FindTenantID figures out the AAD tenant ID of the subscription by making an
|
|
|
|
|
// unauthenticated request to the Get Subscription Details endpoint and parses
|
|
|
|
|
// the value from WWW-Authenticate header.
|
|
|
|
|
|