@@ -2,41 +2,121 @@ package azure
22
33import (
44 "context"
5- "log"
5+ "encoding/json"
6+ "errors"
7+ "io"
8+ "net/http"
9+ "strings"
610
711 "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
812 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice"
913)
1014
11- func GetAzureCredentials (tenantID string ) (context.Context , * azidentity.AzureCLICredential ) {
15+ type Subscription struct {
16+ SubscriptionID string `json:"subscriptionId"`
17+ }
18+
19+ // OAuth 2 token structure
20+ type tokenResponse struct {
21+ AccessToken string `json:"access_token"`
22+ TokenType string `json:"token_type"`
23+ ExpiresIn float64 `json:"expires_in"`
24+ ExtExpiresIn float64 `json:"ext_expires_in"`
25+ }
1226
13- cred , err := azidentity . NewAzureCLICredential ( & azidentity.AzureCLICredentialOptions { TenantID : tenantID })
27+ func GetAzureCredentials ( tenantID string ) ( ctx context. Context , cred * azidentity.DefaultAzureCredential , err error ) {
1428
29+ cred , err = azidentity .NewDefaultAzureCredential (& azidentity.DefaultAzureCredentialOptions {TenantID : tenantID })
1530 if err != nil {
16- log . Fatal ( err )
31+ return nil , nil , err
1732 }
18- ctx := context .Background ()
1933
20- return ctx , cred
34+ ctx = context .Background ()
35+ return ctx , cred , nil
2136}
2237
23- func GetKubeconfig (ctx context.Context , cred azidentity.AzureCLICredential , resourceGroupName string , subscriptionID string , clusterName string ) (kubeconfig []byte ) {
38+ func GetKubeconfig (ctx context.Context , cred azidentity.DefaultAzureCredential , resourceGroupName string , subscriptionID string , clusterName string ) (kubeconfig []byte , err error ) {
2439
2540 mcClient , err := armcontainerservice .NewManagedClustersClient (subscriptionID , & cred , nil )
2641 if err != nil {
27- log . Fatal ( err ) //remake to return nil on error
42+ return nil , err
2843 }
2944
3045 resp , err := mcClient .ListClusterAdminCredentials (ctx , resourceGroupName , clusterName , nil )
3146 if err != nil {
32- log . Fatal ( err )
47+ return nil , err
3348 }
3449
3550 if len (resp .Kubeconfigs ) > 0 {
36- return resp .Kubeconfigs [0 ].Value
51+ return resp .Kubeconfigs [0 ].Value , nil
3752 } else {
38- log .Fatal ("Error: No Kubeconfigs are available" )
39- return
53+ return nil , errors .New ("no kubeconfigs are available" )
54+ }
55+
56+ }
57+
58+ // Returns the first subscription ID
59+ // If no IDs are found, 'empty' is set to true
60+ func GetDefaultSubscriptionID (token string ) (subscriptionID string , err error ) {
61+
62+ req , err := http .NewRequest (http .MethodGet , "https://management.azure.com/subscriptions?api-version=2020-01-01" , nil )
63+ if err != nil {
64+ return "" , err
65+ }
66+ req .Header .Set ("Authorization" , "Bearer " + token )
67+
68+ resp , err := http .DefaultClient .Do (req )
69+ if err != nil {
70+ return "" , err
71+ }
72+ defer resp .Body .Close ()
73+
74+ var subscriptions struct {
75+ Value []Subscription `json:"value"`
76+ }
77+ if err := json .NewDecoder (resp .Body ).Decode (& subscriptions ); err != nil {
78+ return "" , err
4079 }
4180
81+ if len (subscriptions .Value ) == 0 {
82+ return "" , errors .New ("no subscriptions found" )
83+ }
84+ return subscriptions .Value [0 ].SubscriptionID , nil
85+ }
86+
87+ // Returns access token. Failing that, returns non-nil error
88+ // tenantId - Azure tenant ID
89+ // clientId - Client ID. Can pass Service Principal ID
90+ // clientSecret - Client secret. Cant pass Service Principal password
91+ func GetAuthToken (tenantId string , clientId string , clientSecret string ) (string , error ) {
92+ req , err := http .NewRequest (http .MethodPost , "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token" , nil )
93+ if err != nil {
94+ return "" , err
95+ }
96+
97+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
98+
99+ q := req .URL .Query ()
100+ q .Add ("grant_type" , "client_credentials" )
101+ q .Add ("client_id" , clientId )
102+ q .Add ("client_secret" , clientSecret )
103+ q .Add ("scope" , "https://management.azure.com/.default" )
104+
105+ req .Body = io .NopCloser (strings .NewReader (q .Encode ()))
106+ resp , err := http .DefaultClient .Do (req )
107+ if err != nil {
108+ return "" , err
109+ }
110+ defer resp .Body .Close ()
111+
112+ str , err := io .ReadAll (resp .Body )
113+ if err != nil {
114+ return "" , err
115+ }
116+
117+ var token tokenResponse
118+ if err := json .Unmarshal (str , & token ); err != nil {
119+ return "" , err
120+ }
121+ return token .AccessToken , nil
42122}
0 commit comments