pkg/infrastructure/azureAPI/azureApiClient.go (105 lines of code) (raw):
// MIT License
//
// Copyright (c) Microsoft Corporation.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE
package azureAPI
import (
"context"
"time"
"github.com/Azure/azure-sdk-for-go/profiles/latest/authorization/mgmt/authorization"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure/auth"
log "github.com/sirupsen/logrus"
)
type AzureAPIClients struct {
RoleAssignmentsClient authorization.RoleAssignmentsClient
RoleAssignmentsDeletionClient *armauthorization.RoleAssignmentsClient
// RoleDefinitionsClient authorization.RoleDefinitionsClient
DeploymentsClient *armresources.DeploymentsClient
ResourceGroupsClient *armresources.ResourceGroupsClient
// Default CLI Creds
DefaultCred *azidentity.DefaultAzureCredential
defaultAPIBearerToken string
defaultAPIBearerTokenLastCachedTime time.Time
// SPCred *azidentity.ClientSecretCredential
}
const defaultTokenCacheDuration = 10 * time.Minute
func NewAzureAPIClients(subscriptionID string) *AzureAPIClients {
a := &AzureAPIClients{}
err := a.SetApiClients(subscriptionID)
if err != nil {
log.Fatal(err)
}
return a
}
func getAuthorizer() (authorizer autorest.Authorizer, err error) {
// Use the default Azure environment for authentication
authorizer, err = auth.NewAuthorizerFromCLI()
if err != nil {
return nil, err
}
return authorizer, nil
}
type TokenProvider interface {
GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error)
}
func (a *AzureAPIClients) getBearerToken(tp TokenProvider) (bearerToken string, err error) {
opts := policy.TokenRequestOptions{Scopes: []string{"https://management.azure.com/.default"}}
tok, err := tp.GetToken(context.Background(), opts)
if err != nil {
return "", err
}
return tok.Token, nil
}
func (a *AzureAPIClients) SetApiClients(subscriptionId string) error {
authorizer, err := getAuthorizer()
if err != nil {
return err
}
a.DefaultCred, err = azidentity.NewDefaultAzureCredential(nil)
if err != nil {
// log.Fatal(err)
log.Fatal(err)
}
// Set RoleAssignmentsClient
a.RoleAssignmentsClient = authorization.NewRoleAssignmentsClient(subscriptionId)
a.RoleAssignmentsClient.Authorizer = authorizer
if err != nil {
log.Fatal(err)
}
roleAssignmentsDeletionClientFactory, err := armauthorization.NewClientFactory(subscriptionId, a.DefaultCred, nil)
if err != nil {
log.Fatalf("failed to create role assignments deletion client factory: %v", err)
}
a.RoleAssignmentsDeletionClient = roleAssignmentsDeletionClientFactory.NewRoleAssignmentsClient()
// Set RoleDefinitionsClient
// a.RoleDefinitionsClient = authorization.NewRoleDefinitionsClient(subscriptionId)
// a.RoleDefinitionsClient.Authorizer = authorizer
resourcesClientFactory, err := armresources.NewClientFactory(subscriptionId, a.DefaultCred, nil)
if err != nil {
log.Fatal(err)
}
// Set DeploymentsClient
a.DeploymentsClient = resourcesClientFactory.NewDeploymentsClient()
// Set ResourceGroupsClient
a.ResourceGroupsClient, err = armresources.NewResourceGroupsClient(subscriptionId, a.DefaultCred, nil)
if err != nil {
log.Fatal(err)
}
return nil
}
func (a *AzureAPIClients) GetSPBearerToken(tenantID, spClientID, spClientSecret string) (string, error) {
// Get the Service Principal creds
spCred, err := azidentity.NewClientSecretCredential(tenantID, spClientID, spClientSecret, nil)
if err != nil {
log.Error(err)
return "", err
}
bearerToken, err := a.getBearerToken(spCred)
if err != nil {
log.Error(err)
return "", err
}
return bearerToken, nil
}
func (a *AzureAPIClients) GetDefaultAPIBearerToken() (bearerToken string, err error) {
if a.defaultAPIBearerToken == "" || time.Since(a.defaultAPIBearerTokenLastCachedTime) > defaultTokenCacheDuration {
bearerToken, err = a.getBearerToken(a.DefaultCred)
if err != nil {
return "", err
}
a.defaultAPIBearerToken = bearerToken
a.defaultAPIBearerTokenLastCachedTime = time.Now()
log.Infoln("Default API Bearer Token set")
}
return a.defaultAPIBearerToken, nil
}
// func (m *MinPermFinder) RefreshSPAPIAccessBearerToken() error {
// // Get the bearer token for the API access
// bearerToken, err := m.getBearerToken(m.SPCred)
// if err != nil {
// return err
// }
// m.SPCredBearerToken = bearerToken
// return nil
// }
// func (m *MinPermFinder) CreateCustomRoleWithInitialScopeAndPermissions() error {
// initialScope := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", m.SubscriptionID, m.ResourceGroupName)
// // initialScope := fmt.Sprintf("/subscriptions/%s", m.SubscriptionID)
// roleDefinition := authorization.RoleDefinition{
// RoleDefinitionProperties: &authorization.RoleDefinitionProperties{
// RoleName: &m.RoleDefinitionName,
// Description: &m.RoleDefinitionName,
// AssignableScopes: &[]string{
// initialScope,
// },
// Permissions: &[]authorization.Permission{
// {
// Actions: to.StringSlicePtr([]string{
// // "Microsoft.Resources/deployments/read",
// // "Microsoft.Resources/deployments/write",
// }),
// },
// },
// },
// }
// // Create the custom role
// _, err := m.RoleDefinitionsClient.CreateOrUpdate(m.Ctx, initialScope, m.RoleDefinitionID, roleDefinition)
// return err
// }