File

src/providers/azure/azure.provider.ts

Index

Methods

Methods

Async decryptConfig
decryptConfig(azureConfig: AzureConfig)
Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : unknown
Async encryptConfig
encryptConfig(azureConfig: AzureConfig)
Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : unknown
getCredentials
getCredentials(azureConfig: AzureConfig)

Function to get an instance of the ClientSecretCredential with the details needed to authenticate against Microsoft Entra ID with a client secret.

Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : ClientSecretCredential

ClientSecretCredential

Async getResourcesByTags
getResourcesByTags(azureConfig: AzureConfig, tagList: string[])

Function to list resources by tag filter azure resource filter only supports one tag at a time hence in case multiple tags are passed , this function will filter on the first one in tag list

Parameters :
Name Type Optional
azureConfig AzureConfig No
tagList string[] No
Returns : unknown
getSubscriptionScope
getSubscriptionScope(azureConfig: AzureConfig)

Function to get subscription scope string

Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : string

scope string

getTagKyes
getTagKyes(azureConfig: AzureConfig, getTagsInput: TagsListOptionalParams)
Parameters :
Name Type Optional
azureConfig AzureConfig No
getTagsInput TagsListOptionalParams No
Returns : void
Async getTagsData
getTagsData(azureConfig: AzureConfig, getTagsInput: TagsListOptionalParams)

Function to list tags for an azure subscription

Parameters :
Name Type Optional
azureConfig AzureConfig No
getTagsInput TagsListOptionalParams No
Returns : unknown

tags data object

getTagValuesForKey
getTagValuesForKey(azureConfig: AzureConfig, getTagsInput: TagsListOptionalParams)
Parameters :
Name Type Optional
azureConfig AzureConfig No
getTagsInput TagsListOptionalParams No
Returns : void
maskConfigSecret
maskConfigSecret(azureConfig: AzureConfig)
Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : AzureConfig
queryCost
queryCost(azureConfig: AzureConfig, getCostAndUsageInput: QueryDefinition)

Function to query cost data base on input filters

Parameters :
Name Type Optional
azureConfig AzureConfig No
getCostAndUsageInput QueryDefinition No
Returns : any
testConnection
testConnection(azureConfig: AzureConfig)

Function to test connection currently fetches tag list data

Parameters :
Name Type Optional
azureConfig AzureConfig No
Returns : unknown

tags data

import { Injectable } from "@nestjs/common";
import { decryptText, encryptText } from "../../common/helper";
import { ClientSecretCredential } from "@azure/identity";

import {
  QueryDefinition,
  CostManagementClient,
} from "@azure/arm-costmanagement";
import { AzureAuthorityHost, AzureConfig } from "./azure.types";
import {
  ResourceManagementClient,
  ResourcesListOptionalParams,
  TagsListOptionalParams,
} from "@azure/arm-resources";
import { AzureConnectionError } from "./azure.errors";

@Injectable()
export class AzureProvider {
  /**
   * Function to get subscription scope string
   * @param azureConfig
   * @returns scope string
   */
  getSubscriptionScope(azureConfig: AzureConfig): string {
    return `subscriptions/${azureConfig.subscriptionId}`;
  }

  /**
   * Function to get an instance of the ClientSecretCredential with the details needed to authenticate against Microsoft Entra ID with a client secret.
   * @param azureConfig
   * @returns ClientSecretCredential
   */
  getCredentials(azureConfig: AzureConfig): ClientSecretCredential {
    return new ClientSecretCredential(
      azureConfig.tenantId, // tenant_id
      azureConfig.clientId, // client_id
      azureConfig.clientSecret, //client_secret
      {
        authorityHost: AzureAuthorityHost[azureConfig.authorityHost], // should come from frontend
      },
    );
  }

  /**
   * Function to test connection
   * currently fetches tag list data
   * @param azureConfig
   * @returns tags data
   */
  testConnection(azureConfig: AzureConfig) {
    return this.getTagsData(azureConfig, {});
  }

  getTagKyes(azureConfig: AzureConfig, getTagsInput: TagsListOptionalParams) {
    throw new Error(`Method not implemented. for  Subscription: ${azureConfig.subscriptionId} and input: ${getTagsInput}`);
  }

  getTagValuesForKey(
    azureConfig: AzureConfig,
    getTagsInput: TagsListOptionalParams,
  ) {
    throw new Error(`Method not implemented. for  Subscription: ${azureConfig.subscriptionId} and input: ${getTagsInput}`);
  }

  /**
   * Function to list tags for an azure subscription
   * @param azureConfig
   * @param getTagsInput
   * @returns tags data object
   */
  async getTagsData(
    azureConfig: AzureConfig,
    getTagsInput: TagsListOptionalParams,
  ) {
    const credential = this.getCredentials(azureConfig);
    const client = new ResourceManagementClient(
      credential,
      azureConfig.subscriptionId,
    );
    const tagList = [];
    try {
      for await (const item of client.tagsOperations.list(getTagsInput)) {
        item.values.forEach((value) => {
          tagList.push(`${item.tagName}:${value.tagValue}`);
        });
      } 
    } catch (error) {
      console.error("Error fetching tags:", error);

      throw new AzureConnectionError(
        `Failed to fetch tags: ${error}`,
      );
    }
    return tagList;
  }

  /**
   * Function to list resources by tag filter
   * azure resource filter only supports one tag at a time
   * hence in case multiple tags are passed , this function will filter on the first one in tag list
   * @param azureConfig
   * @param tagList
   * @returns
   */
  async getResourcesByTags(azureConfig: AzureConfig, tagList: string[]) {
    const credential = this.getCredentials(azureConfig);
    const client = new ResourceManagementClient(
      credential,
      azureConfig.subscriptionId,
    );
    const resourceList = [];
    const options: ResourcesListOptionalParams = {};

    // azure allows only one tag at a time hence will filter on the very first one
    if (tagList.length > 0) {
      const [key, value] = tagList[0].split(":");
      options["filter"] = `tagName eq '${key}' and tagValue eq '${value}'`;
    }

    try {
      for await (const item of client.resources.list(options)) {
        const tagList = [];
        Object.keys(item.tags).forEach((key) => {
          tagList.push({
            Key: key,
            Value: item.tags[key],
          });
        });
        resourceList.push({
          id: item.id,
          ResourceARN: item.id.toLowerCase(),
          Tags: tagList,
        });
      } 
    } catch (error) {
      console.error("Error fetching resources by tags:", error);

      throw new AzureConnectionError(
        `Failed to fetch resources by tags: ${error}`,
      );
    }

    return {
      ResourceTagMappingList: resourceList,
    };
  }

  /**
   * Function to query cost data base on input filters
   * @param azureConfig
   * @param getCostAndUsageInput
   * @returns
   */
  queryCost(azureConfig: AzureConfig, getCostAndUsageInput: QueryDefinition) {
    const scope = this.getSubscriptionScope(azureConfig);
    const credential = this.getCredentials(azureConfig);
    const client = new CostManagementClient(credential);
    try {
      return client.query.usage(scope, getCostAndUsageInput); 
    } catch (error) {
      console.error("Error fetching cost and usage data:", error);

      throw new AzureConnectionError(
        `Failed to fetch cost and usage data: ${error}`,
      );
    }
  }

  async encryptConfig(azureConfig: AzureConfig) {
    if (
      azureConfig.hasOwnProperty("clientSecret") &&
      azureConfig["clientSecret"]
    ) {
      azureConfig["clientSecret"] = await encryptText(
        azureConfig["clientSecret"],
      );
    }
    return azureConfig;
  }

  async decryptConfig(azureConfig: AzureConfig) {
    if (
      azureConfig.hasOwnProperty("clientSecret") &&
      azureConfig["clientSecret"]
    ) {
      azureConfig["clientSecret"] = await decryptText(
        azureConfig["clientSecret"],
      );
    }
    return azureConfig;
  }

  maskConfigSecret(azureConfig: AzureConfig) {
    if (azureConfig.hasOwnProperty("clientSecret")) {
      delete azureConfig["clientSecret"];
    }
    return azureConfig;
  }
}

results matching ""

    No results matching ""