Merge branch '21521-aptly-flock'
[arvados-dev.git] / compute-image-cleaner / azure.go
1 // Copyright (C) The Azure-Samples Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: MIT
4
5 // Largely borrowed from
6 // https://github.com/Azure-Samples/azure-sdk-for-go-samples/blob/master/internal/iam/authorizers.go
7
8 package main
9
10 import (
11         "fmt"
12         "log"
13
14         "git.arvados.org/arvados-dev.git/compute-image-cleaner/config"
15
16         "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-06-01/storage"
17
18         "github.com/Azure/go-autorest/autorest"
19         "github.com/Azure/go-autorest/autorest/adal"
20         "github.com/Azure/go-autorest/autorest/azure/auth"
21 )
22
23 // OAuthGrantType specifies which grant type to use.
24 type OAuthGrantType int
25
26 const (
27         // OAuthGrantTypeServicePrincipal for client credentials flow
28         OAuthGrantTypeServicePrincipal OAuthGrantType = iota
29         // OAuthGrantTypeDeviceFlow for device flow
30         OAuthGrantTypeDeviceFlow
31 )
32
33 var (
34         armAuthorizer autorest.Authorizer
35 )
36
37 // GrantType returns what grant type has been configured.
38 func grantType() OAuthGrantType {
39         if config.UseDeviceFlow() {
40                 return OAuthGrantTypeDeviceFlow
41         }
42         return OAuthGrantTypeServicePrincipal
43 }
44
45 func getAuthorizerForResource(grantType OAuthGrantType, resource string) (autorest.Authorizer, error) {
46         var a autorest.Authorizer
47         var err error
48
49         switch grantType {
50
51         case OAuthGrantTypeServicePrincipal:
52                 oauthConfig, err := adal.NewOAuthConfig(
53                         config.Environment().ActiveDirectoryEndpoint, config.TenantID())
54                 if err != nil {
55                         return nil, err
56                 }
57
58                 token, err := adal.NewServicePrincipalToken(
59                         *oauthConfig, config.ClientID(), config.ClientSecret(), resource)
60                 if err != nil {
61                         return nil, err
62                 }
63                 a = autorest.NewBearerAuthorizer(token)
64
65         case OAuthGrantTypeDeviceFlow:
66                 deviceconfig := auth.NewDeviceFlowConfig(config.ClientID(), config.TenantID())
67                 deviceconfig.Resource = resource
68                 a, err = deviceconfig.Authorizer()
69                 if err != nil {
70                         return nil, err
71                 }
72
73         default:
74                 return a, fmt.Errorf("invalid grant type specified")
75         }
76
77         return a, err
78 }
79
80 // GetResourceManagementAuthorizer gets an OAuthTokenAuthorizer for Azure Resource Manager
81 func GetResourceManagementAuthorizer() (autorest.Authorizer, error) {
82         if armAuthorizer != nil {
83                 return armAuthorizer, nil
84         }
85
86         var a autorest.Authorizer
87         var err error
88
89         a, err = getAuthorizerForResource(
90                 grantType(), config.Environment().ResourceManagerEndpoint)
91
92         if err == nil {
93                 // cache
94                 armAuthorizer = a
95         } else {
96                 // clear cache
97                 armAuthorizer = nil
98         }
99         return armAuthorizer, err
100 }
101
102 func getStorageAccountsClient() storage.AccountsClient {
103         storageAccountsClient := storage.NewAccountsClient(config.SubscriptionID())
104         auth, err := GetResourceManagementAuthorizer()
105         if err != nil {
106                 log.Fatal(err)
107         }
108         storageAccountsClient.Authorizer = auth
109         err = storageAccountsClient.AddToUserAgent("compute-image-cleaner")
110         if err != nil {
111                 log.Fatal(err)
112         }
113         return storageAccountsClient
114 }