Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add table azure_storage_container. closes #69 #71

Merged
merged 11 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"id": "{{ output.resource_id.value }}",
"name": "{{resourceName}}",
"type": "Microsoft.Storage/storageAccounts/blobServices/containers"
}
]
4 changes: 4 additions & 0 deletions azure-test/tests/azure_storage_container/test-get-query.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select name, id, type
from azure.azure_storage_container
where name = '{{resourceName}}' and resource_group = '{{resourceName}}' and
account_name = '{{resourceName}}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"id": "{{ output.resource_id.value }}",
"name": "{{resourceName}}"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select name, id
from azure.azure_storage_container
where name = '{{resourceName}}' and resource_group = '{{resourceName}}' and
account_name = '{{resourceName}}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"id": "{{ output.resource_id.value }}",
"name": "{{resourceName}}"
}
]
3 changes: 3 additions & 0 deletions azure-test/tests/azure_storage_container/test-list-query.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
select name, id
from azure.azure_storage_container
where id = '{{ output.resource_id.value }}'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
null
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select name, id
from azure.azure_storage_container
where name = 'dummy{{resourceName}}' and resource_group = '{{resourceName}}' and
account_name = '{{resourceName}}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"akas": [
"{{ output.resource_aka.value }}",
"{{ output.resource_aka_lower.value }}"
],
"title": "{{resourceName}}"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
select title, akas
from azure.azure_storage_container
where name = '{{resourceName}}' and resource_group = '{{resourceName}}' and
account_name = '{{resourceName}}'
1 change: 1 addition & 0 deletions azure-test/tests/azure_storage_container/variables.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
72 changes: 72 additions & 0 deletions azure-test/tests/azure_storage_container/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

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 = "d7245080-b4ae-4fe5-b6fa-2e71b3dae6c8"
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
description = "Azure subscription used for the test."
}

provider "azurerm" {
features {}
environment = var.azure_environment
subscription_id = var.azure_subscription
}

data "azurerm_client_config" "current" {}

data "null_data_source" "resource" {
inputs = {
scope = "azure:///subscriptions/${data.azurerm_client_config.current.subscription_id}"
}
}

resource "azurerm_resource_group" "named_test_resource" {
name = var.resource_name
location = "East US"
}

resource "azurerm_storage_account" "named_test_resource" {
name = var.resource_name
resource_group_name = azurerm_resource_group.named_test_resource.name
location = azurerm_resource_group.named_test_resource.location
account_tier = "Standard"
account_kind = "StorageV2"
access_tier = "Cool"
account_replication_type = "LRS"

tags = {
name = var.resource_name
}
}
resource "azurerm_storage_container" "named_test_resource" {
name = var.resource_name
storage_account_name = azurerm_storage_account.named_test_resource.name
container_access_type = "private"
}

output "resource_aka" {
value = "azure:///subscriptions/${var.azure_subscription}/resourceGroups/${var.resource_name}/providers/Microsoft.Storage/storageAccounts/${var.resource_name}/blobServices/default/containers/${var.resource_name}"
}

output "resource_aka_lower" {
value = "azure:///subscriptions/${lower(var.azure_subscription)}/resourcegroups/${lower(var.resource_name)}/providers/microsoft.storage/storageaccounts/${lower(var.resource_name)}/blobservices/default/containers/${lower(var.resource_name)}"
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
}

output "resource_name" {
value = var.resource_name
}

output "resource_id" {
value = "/subscriptions/${var.azure_subscription}/resourceGroups/${var.resource_name}/providers/Microsoft.Storage/storageAccounts/${var.resource_name}/blobServices/default/containers/${var.resource_name}"
}
1 change: 1 addition & 0 deletions azure/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
"azure_storage_table_service": tableAzureStorageTableService(ctx),
"azure_subnet": tableAzureSubnet(ctx),
"azure_virtual_network": tableAzureVirtualNetwork(ctx),
"azure_storage_container": tableAzureStorageContainer(ctx),
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
// "azure_storage_blob": tableAzureStorageBlob(ctx),
// "azure_storage_table": tableAzureStorageTable(ctx),
},
Expand Down
153 changes: 153 additions & 0 deletions azure/table_azure_storage_container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package azure

import (
"context"

"github.com/turbot/steampipe-plugin-sdk/grpc/proto"
"github.com/turbot/steampipe-plugin-sdk/plugin"
"github.com/turbot/steampipe-plugin-sdk/plugin/transform"

"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage"
)

//// TABLE DEFINITION

func tableAzureStorageContainer(_ context.Context) *plugin.Table {
return &plugin.Table{
Name: "azure_storage_container",
Description: "Azure Storage Container",
Get: &plugin.GetConfig{
KeyColumns: plugin.AllColumns([]string{"name", "resource_group", "account_name"}),
Hydrate: getStorageContainer,
ShouldIgnoreError: isNotFoundError([]string{"ResourceNotFound", "ResourceGroupNotFound", "ContainerNotFound"}),
},
List: &plugin.ListConfig{
ParentHydrate: listStorageAccounts,
Hydrate: listStorageContainers,
},

Columns: []*plugin.Column{
// Basic info
{
Name: "name",
Description: "The friendly name that identifies the container.",
Type: proto.ColumnType_STRING,
},
{
Name: "id",
Description: "The container ID",
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ID"),
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
},
{
Name: "type",
Description: "Specifies the type of the container.",
Type: proto.ColumnType_STRING,
},
// Other details
{
Name: "account_name",
Description: "The friendly name that identifies the storage account.",
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ID").Transform(idToAccountName),
},
{
Name: "container_properties",
Description: "The blob container properties.",
Type: proto.ColumnType_JSON,
Transform: transform.FromField("ContainerProperties"),
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
},

// Standard steampipe columns
{
Name: "title",
Description: ColumnDescriptionTitle,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("Name"),
},
{
Name: "tags",
Description: ColumnDescriptionTags,
Type: proto.ColumnType_JSON,
Transform: transform.FromField("Etag"),
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
},
{
Name: "akas",
Description: ColumnDescriptionAkas,
Type: proto.ColumnType_JSON,
Transform: transform.FromField("ID").Transform(idToAkas),
},

// Standard azure columns
{
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
Name: "resource_group",
Description: ColumnDescriptionResourceGroup,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ID").Transform(extractResourceGroupFromID),
},
{
Name: "subscription_id",
Description: ColumnDescriptionSubscription,
Type: proto.ColumnType_STRING,
Transform: transform.FromField("ID").Transform(idToSubscriptionID),
},
},
}
}

//// FETCH FUNCTIONS
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved

func listStorageContainers(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
// Get the details of storage account
account := h.Item.(*storageAccountInfo)

session, err := GetNewSession(ctx, d, "MANAGEMENT")
if err != nil {
return nil, err
}
subscriptionID := session.SubscriptionID

// List all containers
containerClient := storage.NewBlobContainersClient(subscriptionID)
containerClient.Authorizer = session.Authorizer
pagesLeft := true
for pagesLeft {
containerList, err := containerClient.List(ctx, *account.ResourceGroup, *account.Name, "", "", "")
if err != nil {
return nil, err
}

for _, container := range containerList.Values() {
d.StreamLeafListItem(ctx, container)
}
containerList.NextWithContext(context.Background())
pagesLeft = containerList.NotDone()
}

return nil, err
}

//// HYDRATE FUNCTIONS

func getStorageContainer(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
plugin.Logger(ctx).Trace("getStorageContainer")

session, err := GetNewSession(ctx, d, "MANAGEMENT")
if err != nil {
return nil, err
}
subscriptionID := session.SubscriptionID
name := d.KeyColumnQuals["name"].GetStringValue()
resourceGroup := d.KeyColumnQuals["resource_group"].GetStringValue()
accountName := d.KeyColumnQuals["account_name"].GetStringValue()

storageClient := storage.NewBlobContainersClient(subscriptionID)
storageClient.Authorizer = session.Authorizer

op, err := storageClient.Get(ctx, resourceGroup, accountName, name)
if err != nil {
return nil, err
}

return op, nil
}
6 changes: 6 additions & 0 deletions azure/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,9 @@ func toLower(_ context.Context, d *transform.TransformData) (interface{}, error)
valStr := types.SafeString(d.Value)
return strings.ToLower(valStr), nil
}

func idToAccountName(ctx context.Context, d *transform.TransformData) (interface{}, error) {
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
id := types.SafeString(d.Value)
account_name := strings.Split(id, "/")[8]
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
return account_name, nil
}
27 changes: 27 additions & 0 deletions docs/tables/azure_storage_container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Table: azure_storage_container

A container organizes a set of blobs, similar to a directory in a file system. A storage account can include an unlimited number of containers, and a container can store an unlimited number of blobs.

## Examples

### Basic info

```sql
select
name,
id,
type,
account_name
from
azure_storage_container;
```
### Ensure the storage container storing the activity logs is not publicly accessible
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved

```sql
select
jsonb_pretty(container_properties) as container_properties
from
azure_storage_container
where
name = 'insights-operational-logs';
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved
```
bigdatasourav marked this conversation as resolved.
Show resolved Hide resolved