From b98710ad418e28f341270195668a20cf8bd74f25 Mon Sep 17 00:00:00 2001 From: ParthaI Date: Thu, 27 May 2021 09:55:59 +0530 Subject: [PATCH 1/3] Add table azure_tenant closes #140 --- .../tests/azure_tenant/dependencies.txt | 0 .../azure_tenant/test-list-expected.json | 7 ++ .../tests/azure_tenant/test-list-query.sql | 3 + .../azure_tenant/test-notfound-expected.json | 1 + .../azure_tenant/test-notfound-query.sql | 3 + .../azure_tenant/test-turbot-expected.json | 6 + .../tests/azure_tenant/test-turbot-query.sql | 3 + azure-test/tests/azure_tenant/variable.tf | 46 +++++++ azure/plugin.go | 1 + azure/table_azure_tenant.go | 115 ++++++++++++++++++ docs/tables/azure_tenant.md | 21 ++++ 11 files changed, 206 insertions(+) create mode 100644 azure-test/tests/azure_tenant/dependencies.txt create mode 100644 azure-test/tests/azure_tenant/test-list-expected.json create mode 100644 azure-test/tests/azure_tenant/test-list-query.sql create mode 100644 azure-test/tests/azure_tenant/test-notfound-expected.json create mode 100644 azure-test/tests/azure_tenant/test-notfound-query.sql create mode 100644 azure-test/tests/azure_tenant/test-turbot-expected.json create mode 100644 azure-test/tests/azure_tenant/test-turbot-query.sql create mode 100644 azure-test/tests/azure_tenant/variable.tf create mode 100644 azure/table_azure_tenant.go create mode 100644 docs/tables/azure_tenant.md diff --git a/azure-test/tests/azure_tenant/dependencies.txt b/azure-test/tests/azure_tenant/dependencies.txt new file mode 100644 index 00000000..e69de29b diff --git a/azure-test/tests/azure_tenant/test-list-expected.json b/azure-test/tests/azure_tenant/test-list-expected.json new file mode 100644 index 00000000..10abdf6f --- /dev/null +++ b/azure-test/tests/azure_tenant/test-list-expected.json @@ -0,0 +1,7 @@ +[ + { + "display_name": null, + "name": "{{ output.current_tenant_display_name.value }}", + "tenant_id": "{{ output.tenant_id.value }}" + } +] \ No newline at end of file diff --git a/azure-test/tests/azure_tenant/test-list-query.sql b/azure-test/tests/azure_tenant/test-list-query.sql new file mode 100644 index 00000000..0b4119cf --- /dev/null +++ b/azure-test/tests/azure_tenant/test-list-query.sql @@ -0,0 +1,3 @@ +select name, display_name, tenant_id +from azure.azure_tenant +where tenant_id = '{{ output.tenant_id.value }}' diff --git a/azure-test/tests/azure_tenant/test-notfound-expected.json b/azure-test/tests/azure_tenant/test-notfound-expected.json new file mode 100644 index 00000000..ec747fa4 --- /dev/null +++ b/azure-test/tests/azure_tenant/test-notfound-expected.json @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/azure-test/tests/azure_tenant/test-notfound-query.sql b/azure-test/tests/azure_tenant/test-notfound-query.sql new file mode 100644 index 00000000..59a9d4fd --- /dev/null +++ b/azure-test/tests/azure_tenant/test-notfound-query.sql @@ -0,0 +1,3 @@ +select display_name, title +from azure.azure_tenant +where display_name = 'dummy-{{ resourceName }}'; \ No newline at end of file diff --git a/azure-test/tests/azure_tenant/test-turbot-expected.json b/azure-test/tests/azure_tenant/test-turbot-expected.json new file mode 100644 index 00000000..b68eb249 --- /dev/null +++ b/azure-test/tests/azure_tenant/test-turbot-expected.json @@ -0,0 +1,6 @@ +[ + { + "name": "{{ output.current_tenant_display_name.value }}", + "title": "{{ output.current_tenant_display_name.value }}" + } +] \ No newline at end of file diff --git a/azure-test/tests/azure_tenant/test-turbot-query.sql b/azure-test/tests/azure_tenant/test-turbot-query.sql new file mode 100644 index 00000000..e8f31f54 --- /dev/null +++ b/azure-test/tests/azure_tenant/test-turbot-query.sql @@ -0,0 +1,3 @@ +select name, title +from azure.azure_tenant +where tenant_id = '{{ output.tenant_id.value }}'; \ No newline at end of file diff --git a/azure-test/tests/azure_tenant/variable.tf b/azure-test/tests/azure_tenant/variable.tf new file mode 100644 index 00000000..e8d6c989 --- /dev/null +++ b/azure-test/tests/azure_tenant/variable.tf @@ -0,0 +1,46 @@ +variable "resource_name" { + type = string + default = "turbot-test-20200125-create-update" + description = "Name of the resource used throughout the test." +} + +variable "azure_environment" { + type = string + default = "public" + description = "Azure environment used for the test." +} + +variable "azure_subscription" { + type = string + default = "3510ae4d-530b-497d-8f30-53b9616fc6c1" + description = "Azure environment used for the test." +} + +variable "azure_tenant" { + type = string + default = "cdffd708-7da0-4cea-abeb-0a4c334d7f64" + description = "Azure environment used for the test." +} + +provider "azuread" { + # Cannot be passed as a variable + # version = "=0.10.0" + environment = var.azure_environment + subscription_id = var.azure_subscription + tenant_id = var.azure_tenant +} + +data "azurerm_client_config" "current" { +} + +provider "azurerm" { + features {} +} + +output "current_tenant_display_name" { + value = data.azurerm_client_config.current.tenant_id +} + +output "tenant_id" { + value = data.azurerm_client_config.current.tenant_id +} \ No newline at end of file diff --git a/azure/plugin.go b/azure/plugin.go index 9f6fdec0..0f4ef2d2 100644 --- a/azure/plugin.go +++ b/azure/plugin.go @@ -78,6 +78,7 @@ func Plugin(ctx context.Context) *plugin.Plugin { "azure_storage_table_service": tableAzureStorageTableService(ctx), "azure_subnet": tableAzureSubnet(ctx), "azure_subscription": tableAzureSubscription(ctx), + "azure_tenant": tableAzureTenant(ctx), "azure_virtual_network": tableAzureVirtualNetwork(ctx), // "azure_storage_blob": tableAzureStorageBlob(ctx), // "azure_storage_table": tableAzureStorageTable(ctx), diff --git a/azure/table_azure_tenant.go b/azure/table_azure_tenant.go new file mode 100644 index 00000000..ac07f45c --- /dev/null +++ b/azure/table_azure_tenant.go @@ -0,0 +1,115 @@ +package azure + +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-06-01/subscriptions" + "github.com/turbot/steampipe-plugin-sdk/grpc/proto" + "github.com/turbot/steampipe-plugin-sdk/plugin" + "github.com/turbot/steampipe-plugin-sdk/plugin/transform" +) + +//// TABLE DEFINITION + +func tableAzureTenant(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "azure_tenant", + Description: "Azure Tenant", + List: &plugin.ListConfig{ + Hydrate: listTenants, + }, + Columns: []*plugin.Column{ + { + Name: "name", + Type: proto.ColumnType_STRING, + Description: "The display name of the tenant.", + Transform: transform.From(getNameOrID), + }, + { + Name: "id", + Type: proto.ColumnType_STRING, + Description: "The fully qualified ID of the tenant. For example, /tenants/00000000-0000-0000-0000-000000000000.", + Transform: transform.FromGo(), + }, + { + Name: "tenant_id", + Type: proto.ColumnType_STRING, + Description: "The tenant ID. For example, 00000000-0000-0000-0000-000000000000.", + Transform: transform.FromField("TenantID"), + }, + { + Name: "tenant_category", + Type: proto.ColumnType_STRING, + Description: "The tenant category. Possible values include: 'Home', 'ProjectedBy', 'ManagedBy'", + Transform: transform.FromField("TenantCategory").Transform(transform.ToString), + }, + { + Name: "country", + Type: proto.ColumnType_STRING, + Description: "Country/region name of the address for the tenant.", + }, + { + Name: "country_code", + Type: proto.ColumnType_STRING, + Description: "Country/region abbreviation for the tenant.", + }, + { + Name: "display_name", + Type: proto.ColumnType_STRING, + Description: "The list of domains for the tenant.", + }, + { + Name: "domains", + Type: proto.ColumnType_JSON, + Description: "The list of domains for the tenant.", + }, + + // Standard columns + { + Name: "title", + Description: ColumnDescriptionTitle, + Type: proto.ColumnType_STRING, + Transform: transform.From(getNameOrID), + }, + { + Name: "akas", + Description: ColumnDescriptionAkas, + Type: proto.ColumnType_JSON, + Transform: transform.FromField("ID").Transform(idToAkas), + }, + }, + } +} + +//// LIST FUNCTION + +func listTenants(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + session, err := GetNewSession(ctx, d, "MANAGEMENT") + if err != nil { + return nil, err + } + + client := subscriptions.NewTenantsClient() + client.Authorizer = session.Authorizer + + op, err := client.List(ctx) + if err != nil { + return nil, err + } + + for _, resp := range op.Values() { + d.StreamListItem(ctx, resp) + } + + return nil, nil +} + +//// TRANSFORM FUNCTION + +func getNameOrID(ctx context.Context, d *transform.TransformData) (interface{}, error) { + data := d.HydrateItem.(subscriptions.TenantIDDescription) + if data.DisplayName != nil { + return data.DisplayName, nil + } + return data.TenantID, nil +} diff --git a/docs/tables/azure_tenant.md b/docs/tables/azure_tenant.md new file mode 100644 index 00000000..12a7f8b4 --- /dev/null +++ b/docs/tables/azure_tenant.md @@ -0,0 +1,21 @@ +# Table: azure_tenant + +A dedicated and trusted instance of Azure AD that's automatically created when your organization signs up for a Microsoft cloud service subscription, such as Microsoft Azure, Microsoft Intune, or Microsoft 365. An Azure tenant represents a single organization. + +## Examples + +### Basic info + +```sql +select + name, + id, + tenant_id, + tenant_category, + country, + country_code, + display_name, + domains +from + azure_tenant; +``` From c642d6aebd671b61f7398bb3ee10a9dd6262acee Mon Sep 17 00:00:00 2001 From: ParthaI Date: Fri, 28 May 2021 16:17:46 +0530 Subject: [PATCH 2/3] Update idToAkas function for removing duplicate elements from array --- azure/utils.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/azure/utils.go b/azure/utils.go index 0198fc43..e4971ed1 100644 --- a/azure/utils.go +++ b/azure/utils.go @@ -24,6 +24,15 @@ func idToSubscriptionID(ctx context.Context, d *transform.TransformData) (interf func idToAkas(ctx context.Context, d *transform.TransformData) (interface{}, error) { id := types.SafeString(d.Value) akas := []string{"azure://" + id, "azure://" + strings.ToLower(id)} + occured := map[string]bool{} + result := []string{} + for i := range akas { + if !occured[akas[i]] { + occured[akas[i]] = true + result = append(result, akas[i]) + } + } + akas = result return akas, nil } From 09a31d8bcbc8db3d1b14da12e1b70b45ba6fd3f4 Mon Sep 17 00:00:00 2001 From: cbruno10 Date: Wed, 2 Jun 2021 11:21:01 -0400 Subject: [PATCH 3/3] Update table_azure_tenant.go --- azure/table_azure_tenant.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure/table_azure_tenant.go b/azure/table_azure_tenant.go index ac07f45c..f5dd90bb 100644 --- a/azure/table_azure_tenant.go +++ b/azure/table_azure_tenant.go @@ -40,7 +40,7 @@ func tableAzureTenant(_ context.Context) *plugin.Table { { Name: "tenant_category", Type: proto.ColumnType_STRING, - Description: "The tenant category. Possible values include: 'Home', 'ProjectedBy', 'ManagedBy'", + Description: "The tenant category. Possible values include: 'Home', 'ProjectedBy', 'ManagedBy'.", Transform: transform.FromField("TenantCategory").Transform(transform.ToString), }, {