From b02ad5ddf918f294cd1b411910310b028b5d8d60 Mon Sep 17 00:00:00 2001 From: srb3 Date: Tue, 20 Oct 2020 14:22:07 +0100 Subject: [PATCH 1/6] rewrite storage account to new generic resource way Signed-off-by: srb3 --- ...ge_account.rb => azure_storage_account.rb} | 48 +++++++++------ libraries/azure_storage_accounts.rb | 61 +++++++++++++++++++ libraries/azurerm_storage_accounts.rb | 33 ---------- ...ge_account.rb => azure_storage_account.rb} | 4 +- ..._accounts.rb => azure_storage_accounts.rb} | 6 +- 5 files changed, 95 insertions(+), 57 deletions(-) rename libraries/{azurerm_storage_account.rb => azure_storage_account.rb} (51%) create mode 100644 libraries/azure_storage_accounts.rb delete mode 100644 libraries/azurerm_storage_accounts.rb rename test/integration/verify/controls/{azurerm_storage_account.rb => azure_storage_account.rb} (67%) rename test/integration/verify/controls/{azurerm_storage_accounts.rb => azure_storage_accounts.rb} (72%) diff --git a/libraries/azurerm_storage_account.rb b/libraries/azure_storage_account.rb similarity index 51% rename from libraries/azurerm_storage_account.rb rename to libraries/azure_storage_account.rb index 5b3596023..4afe06d39 100644 --- a/libraries/azurerm_storage_account.rb +++ b/libraries/azure_storage_account.rb @@ -1,33 +1,26 @@ -# frozen_string_literal: true - require 'azurerm_resource' -require 'date' -class AzurermStorageAccount < AzurermSingularResource - name 'azurerm_storage_account' +class AzureStorageAccount < AzureGenericResource + name 'azure_storage_account' desc 'Verifies settings for a Azure Storage Account' example <<-EXAMPLE - describe azurerm_storage_account(resource_group: resource_name, name: 'default') do + describe azure_storage_account(resource_group: resource_name, name: 'default') do it { should exist } its('secure_transfer_enabled') { should be true } end EXAMPLE - ATTRS = %i( - name - id - properties - ).freeze - - attr_reader(*ATTRS) - - def initialize(name: 'default', resource_group: nil) - storage_account = management.storage_account(resource_group, name) - return if has_error?(storage_account) + def initialize(opts = {}) + raise ArgumentError, 'Parameters must be provided in a Hash object.' unless opts.is_a?(Hash) + opts[:resource_provider] = specific_resource_constraint('Microsoft.Storage/storageAccounts', opts) + opts[:resource_identifiers] = %i(storage_account_name) - assign_fields(ATTRS, storage_account) + # static_resource parameter must be true for setting the resource_provider in the backend.\ + super(opts, true) + end - @exists = true + def to_s + super(AzureStorageAccount) end def has_recently_generated_access_key? @@ -68,3 +61,20 @@ def to_utc(datetime) datetime.to_time.utc.iso8601 end end + +# Provide the same functionality under the old resource name. +# This is for backward compatibility. +class AzurermStorageAccount < AzureStorageAccount + name 'azurerm_storage_account' + desc 'Verifies settings for an Azure Storage Account' + example <<-EXAMPLE + describe azurerm_storage_account(resource_group: 'rg-1', name: 'sa1') do + it { should exist } + end + EXAMPLE + + def initialize(opts = {}) + Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureStorageAccount.name) + super + end +end diff --git a/libraries/azure_storage_accounts.rb b/libraries/azure_storage_accounts.rb new file mode 100644 index 000000000..cf16e6b3b --- /dev/null +++ b/libraries/azure_storage_accounts.rb @@ -0,0 +1,61 @@ +require 'azure_generic_resources' + +class AzureStorageAccounts < AzureGenericResources + name 'azure_storage_accounts' + desc 'Verifies settings for a collection of Azure Storage Accounts' + example <<-EXAMPLE + describe azure_storage_accounts do + it { should exist } + end + EXAMPLE + + attr_reader :table + + def initialize(opts = {}) + # Options should be Hash type. Otherwise Ruby will raise an error when we try to access the keys. + raise ArgumentError, 'Parameters must be provided in an Hash object.' unless opts.is_a?(Hash) + + opts[:resource_provider] = specific_resource_constraint('Microsoft.Storage/storageAccounts', opts) + + # static_resource parameter must be true for setting the resource_provider in the backend. + super(opts, true) + + # Check if the resource is failed. + # It is recommended to check that after every usage of inherited methods or making API calls. + return if failed_resource? + + # Define the column and field names for FilterTable. + # In most cases, the `column` should be the pluralized form of the `field`. + # @see https://github.com/inspec/inspec/blob/master/docs/dev/filtertable-usage.md + table_schema = [ + { column: :names, field: :name }, + { column: :type, field: :type }, + { column: :location, field: :location }, + { column: :tags, field: :tags }, + ] + + # FilterTable is populated at the very end due to being an expensive operation. + AzureGenericResources.populate_filter_table(:table, table_schema) + end + + def to_s + super(AzureStorageAccounts) + end +end + +# Provide the same functionality under the old resource name. +# This is for backward compatibility. +class AzurermStorageAccounts < AzureStorageAccounts + name 'azurerm_storage_accounts' + desc 'Verifies settings for a collection of Azure Storage Accounts' + example <<-EXAMPLE + describe azurerm_storage_accounts do + it { should exist } + end + EXAMPLE + + def initialize(opts = {}) + Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureStorageAccounts.name) + super + end +end diff --git a/libraries/azurerm_storage_accounts.rb b/libraries/azurerm_storage_accounts.rb deleted file mode 100644 index 3bde3de1f..000000000 --- a/libraries/azurerm_storage_accounts.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -require 'azurerm_resource' - -class StorageAccounts < AzurermPluralResource - name 'azurerm_storage_accounts' - desc 'Fetches all Azure Storage Accounts' - example <<-EXAMPLE - describe azurerm_storage_accounts do - its('names') { should include('default') } - end - EXAMPLE - - FilterTable.create - .register_column(:names, field: 'name') - .register_column(:type, field: 'type') - .register_column(:location, field: 'location') - .register_column(:tags, field: 'tags') - .install_filter_methods_on_resource(self, :table) - - attr_reader :table - - def initialize(resource_group: nil) - resp = management.storage_accounts(resource_group) - return if has_error?(resp) - - @table = resp - end - - def to_s - 'Storage Accounts' - end -end diff --git a/test/integration/verify/controls/azurerm_storage_account.rb b/test/integration/verify/controls/azure_storage_account.rb similarity index 67% rename from test/integration/verify/controls/azurerm_storage_account.rb rename to test/integration/verify/controls/azure_storage_account.rb index 83a9b54e3..59be3ba61 100644 --- a/test/integration/verify/controls/azurerm_storage_account.rb +++ b/test/integration/verify/controls/azure_storage_account.rb @@ -1,8 +1,8 @@ resource_group = input('resource_group', value: nil) storage_account = input('storage_account', value: nil) -control 'azurerm_storage_account' do - describe azurerm_storage_account(resource_group: resource_group, name: storage_account) do +control 'azure_storage_account' do + describe azure_storage_account(resource_group: resource_group, name: storage_account) do it { should exist } it { should have_encryption_enabled } its('properties') { should have_attributes(supportsHttpsTrafficOnly: true) } diff --git a/test/integration/verify/controls/azurerm_storage_accounts.rb b/test/integration/verify/controls/azure_storage_accounts.rb similarity index 72% rename from test/integration/verify/controls/azurerm_storage_accounts.rb rename to test/integration/verify/controls/azure_storage_accounts.rb index 8e112c1f2..a3e6cde5f 100644 --- a/test/integration/verify/controls/azurerm_storage_accounts.rb +++ b/test/integration/verify/controls/azure_storage_accounts.rb @@ -2,13 +2,13 @@ storage_account = input('storage_account', value: nil) location = input('vnet_location', value: nil) -control 'azurerm_storage_accounts' do - describe azurerm_storage_accounts do +control 'azure_storage_accounts' do + describe azure_storage_accounts do its('names') { should include(storage_account) } its('location') { should include(location) } end - describe azurerm_storage_accounts(resource_group: resource_group) do + describe azure_storage_accounts(resource_group: resource_group) do its('names') { should include(storage_account) } its('location') { should include(location) } end From 78125e660e0d4e114f07c5a9103f4a905db4bf97 Mon Sep 17 00:00:00 2001 From: srb3 Date: Tue, 20 Oct 2020 16:46:24 +0100 Subject: [PATCH 2/6] remove duplicate to_s --- libraries/azure_storage_account.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/azure_storage_account.rb b/libraries/azure_storage_account.rb index 4afe06d39..c2bb2b529 100644 --- a/libraries/azure_storage_account.rb +++ b/libraries/azure_storage_account.rb @@ -50,10 +50,6 @@ def queue_properties @queue_properties ||= queue(name).queue_properties end - def to_s - "#{name} Storage Account" - end - private def to_utc(datetime) From af9ef4b5bf3ca749cd9588de9167287e5b000df0 Mon Sep 17 00:00:00 2001 From: srb3 Date: Mon, 9 Nov 2020 09:17:28 +0000 Subject: [PATCH 3/6] adding first pass at storage account docs Signed-off-by: srb3 --- docs/resources/azure_storage_account.md | 89 ++++++++++++++++++++++++ docs/resources/azure_storage_accounts.md | 74 ++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 docs/resources/azure_storage_account.md create mode 100644 docs/resources/azure_storage_accounts.md diff --git a/docs/resources/azure_storage_account.md b/docs/resources/azure_storage_account.md new file mode 100644 index 000000000..78a84beaa --- /dev/null +++ b/docs/resources/azure_storage_account.md @@ -0,0 +1,89 @@ +--- +title: About the azure_storage_account Resource +platform: azure +--- + +# azure_storage_account + +Use the `azure_storage_account` InSpec audit resource to test properties related to a Azure Storage Account. + +## Azure REST API version, endpoint and http client parameters + +This resource interacts with api versions supported by the resource provider. +The `api_version` can be defined as a resource parameter. +If not provided, the latest version will be used. +For more information, refer to [`azure_generic_resource`](azure_generic_resource.md). + +Unless defined, `azure_cloud` global endpoint, and default values for the http client will be used. +For more information, refer to the resource pack [README](../../README.md). + +## Availability + +### Installation + +This resource is available in the [InSpec Azure resource pack](https://github.com/inspec/inspec-azure). +For an example `inspec.yml` file and how to set up your Azure credentials, refer to resource pack [README](../../README.md#Service-Principal). + +## Syntax + +`resource_group` and `name` must be given as a parameter. +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'sa') do + it { should exist } +end +``` +## Parameters + +| Name | Description | +|--------------------------------|--------------------------------------------------------------------------------------| +| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | +| name | The name of the storage account within the specified resource group. `accountName` | + + +## Properties + +| Property | Description | +|---------------------------------------|-------------| +| has_encryption_enabled? | Indicates whether the storage account has encryption enabled| + +Storage account properties documentation [Storage Account API](https://docs.microsoft.com/en-us/rest/api/storagerp/srp_json_get_storage_account_properties#response-body-version-2016-01-01-and-later) + +For properties applicable to all resources, such as `type`, `tags`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties). + +## Examples + +### Test if encryption is enabled +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should have_encryption_enabled } +end +``` + +``` +### Loop through Resources +```ruby +azure_storage_accounts(resource_group: 'rg').name.each do |n| + describe azure_storage_account(resource_group: 'rg', name: n) do + it { should have_encryption_enabled } + end +end +``` +## Matchers + +This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](https://docs.chef.io/inspec/matchers/). + +### exists +```ruby +# If we expect the resource to always exist +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should exist } +end + +# If we expect the resource to never exist +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should_not exist } +end +``` +## Azure Permissions + +Your [Service Principal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal) must be setup with a `contributor` role on the subscription you wish to test. diff --git a/docs/resources/azure_storage_accounts.md b/docs/resources/azure_storage_accounts.md new file mode 100644 index 000000000..7b24c461c --- /dev/null +++ b/docs/resources/azure_storage_accounts.md @@ -0,0 +1,74 @@ +--- +title: About the azure_storage_accounts Resource +platform: azure +--- + +# azure_storage_accounts + +Use the `azure_storage_accounts` InSpec audit resource to test properties and configuration of Azure Storage Accounts. + +## Azure REST API version, endpoint and http client parameters + +This resource interacts with api versions supported by the resource provider. +The `api_version` can be defined as a resource parameter. +If not provided, the latest version will be used. +For more information, refer to [`azure_generic_resource`](azure_generic_resource.md). + +Unless defined, `azure_cloud` global endpoint, and default values for the http client will be used. +For more information, refer to the resource pack [README](../../README.md). + +## Availability + +### Installation + +This resource is available in the [InSpec Azure resource pack](https://github.com/inspec/inspec-azure). +For an example `inspec.yml` file and how to set up your Azure credentials, refer to resource pack [README](../../README.md#Service-Principal). + +## Syntax + +The `resource_group` must be given as a parameter. +```ruby +describe azurerm_storage_accounts(resource_group: 'rg') do + its('names') { should include 'mysa'} +end +``` +## Parameters + +| Name | Description | +|--------------------------------|--------------------------------------------------------------------------------------| +| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | + +## Properties + +|Property | Description | Filter Criteria* | +|---------------|--------------------------------------------------------------------------------------|-----------------| +| names | A list of names of all the resources being interrogated. | `name` | + +* For information on how to use filter criteria on plural resources refer to [FilterTable usage](https://github.com/inspec/inspec/blob/master/dev-docs/filtertable-usage.md). + +## Examples + +### Check If a Specific Storage Account Exists +```ruby +describe azurerm_storage_accounts(resource_group: 'rg') do + its('names') { should include('mysa') } +end +``` +### exists + +The control will pass if the filter returns at least one result. Use `should_not` if you expect zero matches. +```ruby +# If we expect at least one account to exisit in a resource group +describe azurerm_storage_accounts(resource_group: 'rg') do + it { should exist } +end + +# If we expect no storage accounts to exist in a resource group +describe azurerm_storage_accounts(resource_group: 'rg') do + it { should_not exist } +end + +``` +## Azure Permissions + +Your [Service Principal](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal) must be setup with a `contributor` role on the subscription you wish to test. From d65b28ec1a8d6d8cdf09fe511626f8c5817800c5 Mon Sep 17 00:00:00 2001 From: Omer Demirok Date: Mon, 9 Nov 2020 14:47:03 +0000 Subject: [PATCH 4/6] Updat azure storage account Signed-off-by: Omer Demirok --- README.md | 2 + docs/resources/azure_storage_account.md | 77 +++++++++++++---- docs/resources/azure_storage_accounts.md | 32 ++++--- libraries/azure_storage_account.rb | 83 +++++++++++++++---- libraries/azure_storage_accounts.rb | 1 + .../verify/controls/azure_storage_account.rb | 2 + .../resources/azure_storage_account_test.rb | 17 ++++ .../resources/azure_storage_accounts_test.rb | 25 ++++++ 8 files changed, 198 insertions(+), 41 deletions(-) create mode 100644 test/unit/resources/azure_storage_account_test.rb create mode 100644 test/unit/resources/azure_storage_accounts_test.rb diff --git a/README.md b/README.md index 7e1616b97..bb5bde3d3 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,8 @@ The static resources derived from the generic resources prepended with `azure_` - [azure_sql_databases](docs/resources/azure_sql_databases.md) - [azure_sql_server](docs/resources/azure_sql_server.md) - [azure_sql_servers](docs/resources/azure_sql_servers.md) +- [azure_storage_account](docs/resources/azure_storage_account.md) +- [azure_storage_accounts](docs/resources/azure_storage_accounts.md) - [azure_storage_account_blob_container](docs/resources/azure_storage_account_blob_container.md) - [azure_storage_account_blob_containers](docs/resources/azure_storage_account_blob_containers.md) - [azure_subnet](docs/resources/azure_subnet.md) diff --git a/docs/resources/azure_storage_account.md b/docs/resources/azure_storage_account.md index 78a84beaa..2d31a6a2f 100644 --- a/docs/resources/azure_storage_account.md +++ b/docs/resources/azure_storage_account.md @@ -5,7 +5,7 @@ platform: azure # azure_storage_account -Use the `azure_storage_account` InSpec audit resource to test properties related to a Azure Storage Account. +Use the `azure_storage_account` InSpec audit resource to test properties related to an Azure Storage Account. ## Azure REST API version, endpoint and http client parameters @@ -26,52 +26,95 @@ For an example `inspec.yml` file and how to set up your Azure credentials, refer ## Syntax -`resource_group` and `name` must be given as a parameter. +An `azure_storage_account` resource block identifies an Azure storage account by `name` and `resource_group` or the `resource_id`. ```ruby describe azure_storage_account(resource_group: 'rg', name: 'sa') do it { should exist } end ``` +```ruby +describe azure_aks_cluster(resource_id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.ContainerService/managedClusters/{ClusterName}') do + it { should exist } +end +``` ## Parameters | Name | Description | |--------------------------------|--------------------------------------------------------------------------------------| | resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | -| name | The name of the storage account within the specified resource group. `accountName` | +| name | The name of the storage account within the specified resource group. `accountName` | +| resource_id | The unique resource ID. `/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}` | +| activity_log_alert_api_version | The activity log alerts endpoint api version used in `have_recently_generated_access_key` matcher. The latest version will be used unless provided. | +| storage_service_endpoint_api_version | The storage service endpoint api version. `2019-12-12` wil be used unless provided. | +Either one of the parameter sets can be provided for a valid query: +- `resource_id` +- `resource_group` and `name` ## Properties -| Property | Description | -|---------------------------------------|-------------| -| has_encryption_enabled? | Indicates whether the storage account has encryption enabled| +| Property | Description | +|----------------------------------------------|-------------| +| queues* | Lists all of the queues in a given storage account. See [here](https://docs.microsoft.com/en-us/rest/api/storageservices/list-queues1) for more. +| queue_properties* | gets the properties of a storage account’s Queue service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. See [here](https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-service-properties) for more. -Storage account properties documentation [Storage Account API](https://docs.microsoft.com/en-us/rest/api/storagerp/srp_json_get_storage_account_properties#response-body-version-2016-01-01-and-later) +*: Note that the Azure endpoints return data in XML format; however, they will be converted to Azure Resource Probe to make the properties accessible via dot notation. +The property names will be in snake case, `propety_name`. Therefore, `` can be tested via `its('enumeration_results.service_endpoint)`. -For properties applicable to all resources, such as `type`, `tags`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties). +For properties applicable to all resources, such as `type`, `name`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties). + +Also, refer to [Azure documentation](https://docs.microsoft.com/en-us/rest/api/storagerp/storageaccounts/getproperties#storageaccount) for other properties available. +Any attribute in the response may be accessed with the key names separated by dots (`.`). ## Examples -### Test if encryption is enabled +### Test the Primary Endpoints ```ruby describe azure_storage_account(resource_group: 'rg', name: 'mysa') do - it { should have_encryption_enabled } + its('properties.primaryEndpoints.blob') { should cmp 'https://mysa.blob.core.windows.net/' } + its('properties.primaryEndpoints.queue') { should cmp 'https://mysa.queue.core.windows.net/' } + its('properties.primaryEndpoints.table') { should cmp 'https://mysa.table.core.windows.net/' } + its('properties.primaryEndpoints.file') { should cmp 'https://mysa.file.core.windows.net/' } end ``` - +### Verify that Only HTTPs is Supported +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('properties.supportsHttpsTrafficOnly') { should be true } +end ``` -### Loop through Resources +### Test Queues Service Endpoint ```ruby -azure_storage_accounts(resource_group: 'rg').name.each do |n| - describe azure_storage_account(resource_group: 'rg', name: n) do - it { should have_encryption_enabled } - end -end +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('queues.enumeration_results.service_endpoint') { should cmp 'https://mysa.queue.core.windows.net/' } +end +``` +### Test Queue Properties Logging Version +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('queue_properties.logging.version') { should cmp '1.0' } +end ``` ## Matchers This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](https://docs.chef.io/inspec/matchers/). +### have_encryption_enabled + +Test if encryption is enabled. +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should have_encryption_enabled } +end +``` +### have_recently_generated_access_key + +Test if an access key has been generated within the last **90** days. +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should have_recently_generated_access_key } +end +``` ### exists ```ruby # If we expect the resource to always exist diff --git a/docs/resources/azure_storage_accounts.md b/docs/resources/azure_storage_accounts.md index 7b24c461c..a40cf95a7 100644 --- a/docs/resources/azure_storage_accounts.md +++ b/docs/resources/azure_storage_accounts.md @@ -5,7 +5,7 @@ platform: azure # azure_storage_accounts -Use the `azure_storage_accounts` InSpec audit resource to test properties and configuration of Azure Storage Accounts. +Use the `azure_storage_accounts` InSpec audit resource to test properties and configuration of multiple Azure Storage Accounts. ## Azure REST API version, endpoint and http client parameters @@ -26,23 +26,31 @@ For an example `inspec.yml` file and how to set up your Azure credentials, refer ## Syntax -The `resource_group` must be given as a parameter. +An `azure_storage_accounts` resource block returns all Azure storape accounts, either within a Resource Group (if provided), or within an entire Subscription. ```ruby -describe azurerm_storage_accounts(resource_group: 'rg') do - its('names') { should include 'mysa'} +describe azure_storage_accounts do + #... +end +``` +or +```ruby +describe azure_storage_accounts(resource_group: 'my-rg') do + #... end ``` ## Parameters -| Name | Description | -|--------------------------------|--------------------------------------------------------------------------------------| -| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | +- `resource_group` (Optional) ## Properties |Property | Description | Filter Criteria* | |---------------|--------------------------------------------------------------------------------------|-----------------| +| ids | A list of the unique resource ids. | `id` | +| locations | A list of locations for all the resources being interrogated. | `location` | | names | A list of names of all the resources being interrogated. | `name` | +| type | A list of types of all the resources being interrogated. | `type` | +| tags | A list of `tag:value` pairs defined on the resources being interrogated. | `tags` | * For information on how to use filter criteria on plural resources refer to [FilterTable usage](https://github.com/inspec/inspec/blob/master/dev-docs/filtertable-usage.md). @@ -54,17 +62,21 @@ describe azurerm_storage_accounts(resource_group: 'rg') do its('names') { should include('mysa') } end ``` +## Matchers + +This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](https://www.inspec.io/docs/reference/matchers/). + ### exists The control will pass if the filter returns at least one result. Use `should_not` if you expect zero matches. ```ruby -# If we expect at least one account to exisit in a resource group -describe azurerm_storage_accounts(resource_group: 'rg') do +# If we expect at least one account to exist in a resource group +describe azure_storage_accounts(resource_group: 'rg') do it { should exist } end # If we expect no storage accounts to exist in a resource group -describe azurerm_storage_accounts(resource_group: 'rg') do +describe azure_storage_accounts(resource_group: 'rg') do it { should_not exist } end diff --git a/libraries/azure_storage_account.rb b/libraries/azure_storage_account.rb index c2bb2b529..4c752a65c 100644 --- a/libraries/azure_storage_account.rb +++ b/libraries/azure_storage_account.rb @@ -1,29 +1,41 @@ -require 'azurerm_resource' +require 'azure_generic_resource' +require 'active_support/core_ext/hash' class AzureStorageAccount < AzureGenericResource name 'azure_storage_account' desc 'Verifies settings for a Azure Storage Account' example <<-EXAMPLE - describe azure_storage_account(resource_group: resource_name, name: 'default') do + describe azure_storage_account(resource_group: 'r-group', name: 'default') do it { should exist } - its('secure_transfer_enabled') { should be true } end EXAMPLE def initialize(opts = {}) - raise ArgumentError, 'Parameters must be provided in a Hash object.' unless opts.is_a?(Hash) + # Options should be Hash type. Otherwise Ruby will raise an error when we try to access the keys. + raise ArgumentError, 'Parameters must be provided in an Hash object.' unless opts.is_a?(Hash) + opts[:resource_provider] = specific_resource_constraint('Microsoft.Storage/storageAccounts', opts) - opts[:resource_identifiers] = %i(storage_account_name) + opts[:allowed_parameters] = %i(activity_log_alert_api_version storage_service_endpoint_api_version) + # fall-back `api_version` is fixed for now. + # TODO: Implement getting the latest Azure Storage services api version + opts[:storage_service_endpoint_api_version] ||= '2019-12-12' + opts[:activity_log_alert_api_version] ||= 'latest' - # static_resource parameter must be true for setting the resource_provider in the backend.\ + # static_resource parameter must be true for setting the resource_provider in the backend. super(opts, true) end def to_s - super(AzureStorageAccount) + super(AzureKeyVault) end + # Resource specific methods can be created. + # `return unless exists?` is necessary to prevent any unforeseen Ruby error. + # Following methods are created to provide the same functionality with the current resource pack >>>> + # @see https://github.com/inspec/inspec-azure + def has_recently_generated_access_key? + return unless exists? now = Time.now ninety_days_ago = ((60*60)*(24*90)) upper_bound = to_utc(now) @@ -33,25 +45,68 @@ def has_recently_generated_access_key? "eventTimestamp ge '#{lower_bound}' and "\ "eventTimestamp le '#{upper_bound}' and "\ "operations eq 'Microsoft.Storage/storageAccounts/regeneratekey/action'" - - log_events = management.activity_log_alert_filtered(filter) - log_events.any? + activity_log_alert_filter(filter) unless respond_to?(:activity_log_alert_filtered) + activity_log_alert_filtered.any? end def has_encryption_enabled? + return unless exists? properties.encryption.services.blob.enabled || false end def queues - @queues ||= queue(name).queues + return unless exists? + url = "https://#{name}.queue#{@azure.storage_endpoint_suffix}" + param = { comp: 'list' } + # Calls to Azure Storage resources requires a special header `x-ms-version` + # https://docs.microsoft.com/en-us/rest/api/storageservices/versioning-for-the-azure-storage-services + headers = { 'x-ms-version' => @opts[:storage_service_endpoint_api_version] } + body = @azure.rest_get_call(url, param, headers) + return unless body + body_hash = Hash.from_xml(body) + hash_with_snakecase_keys = RecursiveMethodHelper.method_recursive(body_hash, :snakecase) + if hash_with_snakecase_keys + create_resource_methods({ queues: hash_with_snakecase_keys }) + public_send(:queues) if respond_to?(:queues) + end end def queue_properties - @queue_properties ||= queue(name).queue_properties + return unless exists? + url = "https://#{name}.queue#{@azure.storage_endpoint_suffix}" + param = { restype: 'service', comp: 'properties' } + # @see #queues for the header `x-ms-version` + headers = { 'x-ms-version' => @opts[:storage_service_endpoint_api_version] } + body = @azure.rest_get_call(url, param, headers) + return unless body + body_hash = Hash.from_xml(body) + hash_with_snakecase_keys = RecursiveMethodHelper.method_recursive(body_hash, :snakecase) + properties = hash_with_snakecase_keys['storage_service_properties'] + if properties + create_resource_methods({ queue_properties: properties }) + public_send(:queue_properties) if respond_to?(:queue_properties) + end end private + # @see AzureKeyVault#diagnostic_settings for how to use #additional_resource_properties method. + # + def activity_log_alert_filter(filter) + return unless exists? + # `additional_resource_properties` method will create a singleton method with the `property_name` + # and make api response available through this property. + additional_resource_properties( + { + property_name: 'activity_log_alert_filtered', + property_endpoint: '/providers/microsoft.insights/eventtypes/management/values', + add_subscription_id: true, + api_version: @opts[:activity_log_alert_api_version], + filter_free_text: filter, + }, + ) + end + def to_utc(datetime) # API requires times in UTC ISO8601 format. datetime.to_time.utc.iso8601 @@ -62,9 +117,9 @@ def to_utc(datetime) # This is for backward compatibility. class AzurermStorageAccount < AzureStorageAccount name 'azurerm_storage_account' - desc 'Verifies settings for an Azure Storage Account' + desc 'Verifies settings for a Azure Storage Account' example <<-EXAMPLE - describe azurerm_storage_account(resource_group: 'rg-1', name: 'sa1') do + describe azurerm_storage_account(resource_group: resource_name, name: 'default') do it { should exist } end EXAMPLE diff --git a/libraries/azure_storage_accounts.rb b/libraries/azure_storage_accounts.rb index cf16e6b3b..1d21c48a7 100644 --- a/libraries/azure_storage_accounts.rb +++ b/libraries/azure_storage_accounts.rb @@ -29,6 +29,7 @@ def initialize(opts = {}) # @see https://github.com/inspec/inspec/blob/master/docs/dev/filtertable-usage.md table_schema = [ { column: :names, field: :name }, + { column: :ids, field: :id }, { column: :type, field: :type }, { column: :location, field: :location }, { column: :tags, field: :tags }, diff --git a/test/integration/verify/controls/azure_storage_account.rb b/test/integration/verify/controls/azure_storage_account.rb index 59be3ba61..6970ca938 100644 --- a/test/integration/verify/controls/azure_storage_account.rb +++ b/test/integration/verify/controls/azure_storage_account.rb @@ -5,6 +5,8 @@ describe azure_storage_account(resource_group: resource_group, name: storage_account) do it { should exist } it { should have_encryption_enabled } + it { should_not have_recently_generated_access_key } its('properties') { should have_attributes(supportsHttpsTrafficOnly: true) } + its('queues.enumeration_results.service_endpoint') { should include(storage_account) } end end diff --git a/test/unit/resources/azure_storage_account_test.rb b/test/unit/resources/azure_storage_account_test.rb new file mode 100644 index 000000000..8b0b271bf --- /dev/null +++ b/test/unit/resources/azure_storage_account_test.rb @@ -0,0 +1,17 @@ +require_relative 'helper' +require 'azure_storage_account' + +class AzureStorageAccountConstructorTest < Minitest::Test + def test_empty_param_not_ok + assert_raises(ArgumentError) { AzureStorageAccount.new } + end + + # resource_provider should not be allowed. + def test_resource_provider_not_ok + assert_raises(ArgumentError) { AzureStorageAccount.new(resource_provider: 'some_type') } + end + + def test_resource_group + assert_raises(ArgumentError) { AzureStorageAccount.new(name: 'my-name') } + end +end diff --git a/test/unit/resources/azure_storage_accounts_test.rb b/test/unit/resources/azure_storage_accounts_test.rb new file mode 100644 index 000000000..f79bd7f71 --- /dev/null +++ b/test/unit/resources/azure_storage_accounts_test.rb @@ -0,0 +1,25 @@ +require_relative 'helper' +require 'azure_storage_accounts' + +class AzureStorageAccountsConstructorTest < Minitest::Test + # resource_type should not be allowed. + def test_resource_type_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(resource_provider: 'some_type') } + end + + def tag_value_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(tag_value: 'some_tag_value') } + end + + def tag_name_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(tag_name: 'some_tag_name') } + end + + def test_resource_id_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(resource_id: 'some_id') } + end + + def test_name_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(name: 'some_name') } + end +end From a36cba05231f5e08eed24f409cdf1c735fd66654 Mon Sep 17 00:00:00 2001 From: Omer Demirok Date: Mon, 9 Nov 2020 14:47:03 +0000 Subject: [PATCH 5/6] Update azure storage account resource Signed-off-by: Omer Demirok --- README.md | 2 + docs/resources/azure_storage_account.md | 77 +++++++++++++---- docs/resources/azure_storage_accounts.md | 32 ++++--- libraries/azure_storage_account.rb | 83 +++++++++++++++---- libraries/azure_storage_accounts.rb | 1 + .../verify/controls/azure_storage_account.rb | 2 + .../resources/azure_storage_account_test.rb | 17 ++++ .../resources/azure_storage_accounts_test.rb | 25 ++++++ 8 files changed, 198 insertions(+), 41 deletions(-) create mode 100644 test/unit/resources/azure_storage_account_test.rb create mode 100644 test/unit/resources/azure_storage_accounts_test.rb diff --git a/README.md b/README.md index 7e1616b97..bb5bde3d3 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,8 @@ The static resources derived from the generic resources prepended with `azure_` - [azure_sql_databases](docs/resources/azure_sql_databases.md) - [azure_sql_server](docs/resources/azure_sql_server.md) - [azure_sql_servers](docs/resources/azure_sql_servers.md) +- [azure_storage_account](docs/resources/azure_storage_account.md) +- [azure_storage_accounts](docs/resources/azure_storage_accounts.md) - [azure_storage_account_blob_container](docs/resources/azure_storage_account_blob_container.md) - [azure_storage_account_blob_containers](docs/resources/azure_storage_account_blob_containers.md) - [azure_subnet](docs/resources/azure_subnet.md) diff --git a/docs/resources/azure_storage_account.md b/docs/resources/azure_storage_account.md index 78a84beaa..2d31a6a2f 100644 --- a/docs/resources/azure_storage_account.md +++ b/docs/resources/azure_storage_account.md @@ -5,7 +5,7 @@ platform: azure # azure_storage_account -Use the `azure_storage_account` InSpec audit resource to test properties related to a Azure Storage Account. +Use the `azure_storage_account` InSpec audit resource to test properties related to an Azure Storage Account. ## Azure REST API version, endpoint and http client parameters @@ -26,52 +26,95 @@ For an example `inspec.yml` file and how to set up your Azure credentials, refer ## Syntax -`resource_group` and `name` must be given as a parameter. +An `azure_storage_account` resource block identifies an Azure storage account by `name` and `resource_group` or the `resource_id`. ```ruby describe azure_storage_account(resource_group: 'rg', name: 'sa') do it { should exist } end ``` +```ruby +describe azure_aks_cluster(resource_id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.ContainerService/managedClusters/{ClusterName}') do + it { should exist } +end +``` ## Parameters | Name | Description | |--------------------------------|--------------------------------------------------------------------------------------| | resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | -| name | The name of the storage account within the specified resource group. `accountName` | +| name | The name of the storage account within the specified resource group. `accountName` | +| resource_id | The unique resource ID. `/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}` | +| activity_log_alert_api_version | The activity log alerts endpoint api version used in `have_recently_generated_access_key` matcher. The latest version will be used unless provided. | +| storage_service_endpoint_api_version | The storage service endpoint api version. `2019-12-12` wil be used unless provided. | +Either one of the parameter sets can be provided for a valid query: +- `resource_id` +- `resource_group` and `name` ## Properties -| Property | Description | -|---------------------------------------|-------------| -| has_encryption_enabled? | Indicates whether the storage account has encryption enabled| +| Property | Description | +|----------------------------------------------|-------------| +| queues* | Lists all of the queues in a given storage account. See [here](https://docs.microsoft.com/en-us/rest/api/storageservices/list-queues1) for more. +| queue_properties* | gets the properties of a storage account’s Queue service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. See [here](https://docs.microsoft.com/en-us/rest/api/storageservices/get-queue-service-properties) for more. -Storage account properties documentation [Storage Account API](https://docs.microsoft.com/en-us/rest/api/storagerp/srp_json_get_storage_account_properties#response-body-version-2016-01-01-and-later) +*: Note that the Azure endpoints return data in XML format; however, they will be converted to Azure Resource Probe to make the properties accessible via dot notation. +The property names will be in snake case, `propety_name`. Therefore, `` can be tested via `its('enumeration_results.service_endpoint)`. -For properties applicable to all resources, such as `type`, `tags`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties). +For properties applicable to all resources, such as `type`, `name`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties). + +Also, refer to [Azure documentation](https://docs.microsoft.com/en-us/rest/api/storagerp/storageaccounts/getproperties#storageaccount) for other properties available. +Any attribute in the response may be accessed with the key names separated by dots (`.`). ## Examples -### Test if encryption is enabled +### Test the Primary Endpoints ```ruby describe azure_storage_account(resource_group: 'rg', name: 'mysa') do - it { should have_encryption_enabled } + its('properties.primaryEndpoints.blob') { should cmp 'https://mysa.blob.core.windows.net/' } + its('properties.primaryEndpoints.queue') { should cmp 'https://mysa.queue.core.windows.net/' } + its('properties.primaryEndpoints.table') { should cmp 'https://mysa.table.core.windows.net/' } + its('properties.primaryEndpoints.file') { should cmp 'https://mysa.file.core.windows.net/' } end ``` - +### Verify that Only HTTPs is Supported +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('properties.supportsHttpsTrafficOnly') { should be true } +end ``` -### Loop through Resources +### Test Queues Service Endpoint ```ruby -azure_storage_accounts(resource_group: 'rg').name.each do |n| - describe azure_storage_account(resource_group: 'rg', name: n) do - it { should have_encryption_enabled } - end -end +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('queues.enumeration_results.service_endpoint') { should cmp 'https://mysa.queue.core.windows.net/' } +end +``` +### Test Queue Properties Logging Version +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + its('queue_properties.logging.version') { should cmp '1.0' } +end ``` ## Matchers This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](https://docs.chef.io/inspec/matchers/). +### have_encryption_enabled + +Test if encryption is enabled. +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should have_encryption_enabled } +end +``` +### have_recently_generated_access_key + +Test if an access key has been generated within the last **90** days. +```ruby +describe azure_storage_account(resource_group: 'rg', name: 'mysa') do + it { should have_recently_generated_access_key } +end +``` ### exists ```ruby # If we expect the resource to always exist diff --git a/docs/resources/azure_storage_accounts.md b/docs/resources/azure_storage_accounts.md index 7b24c461c..a40cf95a7 100644 --- a/docs/resources/azure_storage_accounts.md +++ b/docs/resources/azure_storage_accounts.md @@ -5,7 +5,7 @@ platform: azure # azure_storage_accounts -Use the `azure_storage_accounts` InSpec audit resource to test properties and configuration of Azure Storage Accounts. +Use the `azure_storage_accounts` InSpec audit resource to test properties and configuration of multiple Azure Storage Accounts. ## Azure REST API version, endpoint and http client parameters @@ -26,23 +26,31 @@ For an example `inspec.yml` file and how to set up your Azure credentials, refer ## Syntax -The `resource_group` must be given as a parameter. +An `azure_storage_accounts` resource block returns all Azure storape accounts, either within a Resource Group (if provided), or within an entire Subscription. ```ruby -describe azurerm_storage_accounts(resource_group: 'rg') do - its('names') { should include 'mysa'} +describe azure_storage_accounts do + #... +end +``` +or +```ruby +describe azure_storage_accounts(resource_group: 'my-rg') do + #... end ``` ## Parameters -| Name | Description | -|--------------------------------|--------------------------------------------------------------------------------------| -| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | +- `resource_group` (Optional) ## Properties |Property | Description | Filter Criteria* | |---------------|--------------------------------------------------------------------------------------|-----------------| +| ids | A list of the unique resource ids. | `id` | +| locations | A list of locations for all the resources being interrogated. | `location` | | names | A list of names of all the resources being interrogated. | `name` | +| type | A list of types of all the resources being interrogated. | `type` | +| tags | A list of `tag:value` pairs defined on the resources being interrogated. | `tags` | * For information on how to use filter criteria on plural resources refer to [FilterTable usage](https://github.com/inspec/inspec/blob/master/dev-docs/filtertable-usage.md). @@ -54,17 +62,21 @@ describe azurerm_storage_accounts(resource_group: 'rg') do its('names') { should include('mysa') } end ``` +## Matchers + +This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](https://www.inspec.io/docs/reference/matchers/). + ### exists The control will pass if the filter returns at least one result. Use `should_not` if you expect zero matches. ```ruby -# If we expect at least one account to exisit in a resource group -describe azurerm_storage_accounts(resource_group: 'rg') do +# If we expect at least one account to exist in a resource group +describe azure_storage_accounts(resource_group: 'rg') do it { should exist } end # If we expect no storage accounts to exist in a resource group -describe azurerm_storage_accounts(resource_group: 'rg') do +describe azure_storage_accounts(resource_group: 'rg') do it { should_not exist } end diff --git a/libraries/azure_storage_account.rb b/libraries/azure_storage_account.rb index c2bb2b529..4c752a65c 100644 --- a/libraries/azure_storage_account.rb +++ b/libraries/azure_storage_account.rb @@ -1,29 +1,41 @@ -require 'azurerm_resource' +require 'azure_generic_resource' +require 'active_support/core_ext/hash' class AzureStorageAccount < AzureGenericResource name 'azure_storage_account' desc 'Verifies settings for a Azure Storage Account' example <<-EXAMPLE - describe azure_storage_account(resource_group: resource_name, name: 'default') do + describe azure_storage_account(resource_group: 'r-group', name: 'default') do it { should exist } - its('secure_transfer_enabled') { should be true } end EXAMPLE def initialize(opts = {}) - raise ArgumentError, 'Parameters must be provided in a Hash object.' unless opts.is_a?(Hash) + # Options should be Hash type. Otherwise Ruby will raise an error when we try to access the keys. + raise ArgumentError, 'Parameters must be provided in an Hash object.' unless opts.is_a?(Hash) + opts[:resource_provider] = specific_resource_constraint('Microsoft.Storage/storageAccounts', opts) - opts[:resource_identifiers] = %i(storage_account_name) + opts[:allowed_parameters] = %i(activity_log_alert_api_version storage_service_endpoint_api_version) + # fall-back `api_version` is fixed for now. + # TODO: Implement getting the latest Azure Storage services api version + opts[:storage_service_endpoint_api_version] ||= '2019-12-12' + opts[:activity_log_alert_api_version] ||= 'latest' - # static_resource parameter must be true for setting the resource_provider in the backend.\ + # static_resource parameter must be true for setting the resource_provider in the backend. super(opts, true) end def to_s - super(AzureStorageAccount) + super(AzureKeyVault) end + # Resource specific methods can be created. + # `return unless exists?` is necessary to prevent any unforeseen Ruby error. + # Following methods are created to provide the same functionality with the current resource pack >>>> + # @see https://github.com/inspec/inspec-azure + def has_recently_generated_access_key? + return unless exists? now = Time.now ninety_days_ago = ((60*60)*(24*90)) upper_bound = to_utc(now) @@ -33,25 +45,68 @@ def has_recently_generated_access_key? "eventTimestamp ge '#{lower_bound}' and "\ "eventTimestamp le '#{upper_bound}' and "\ "operations eq 'Microsoft.Storage/storageAccounts/regeneratekey/action'" - - log_events = management.activity_log_alert_filtered(filter) - log_events.any? + activity_log_alert_filter(filter) unless respond_to?(:activity_log_alert_filtered) + activity_log_alert_filtered.any? end def has_encryption_enabled? + return unless exists? properties.encryption.services.blob.enabled || false end def queues - @queues ||= queue(name).queues + return unless exists? + url = "https://#{name}.queue#{@azure.storage_endpoint_suffix}" + param = { comp: 'list' } + # Calls to Azure Storage resources requires a special header `x-ms-version` + # https://docs.microsoft.com/en-us/rest/api/storageservices/versioning-for-the-azure-storage-services + headers = { 'x-ms-version' => @opts[:storage_service_endpoint_api_version] } + body = @azure.rest_get_call(url, param, headers) + return unless body + body_hash = Hash.from_xml(body) + hash_with_snakecase_keys = RecursiveMethodHelper.method_recursive(body_hash, :snakecase) + if hash_with_snakecase_keys + create_resource_methods({ queues: hash_with_snakecase_keys }) + public_send(:queues) if respond_to?(:queues) + end end def queue_properties - @queue_properties ||= queue(name).queue_properties + return unless exists? + url = "https://#{name}.queue#{@azure.storage_endpoint_suffix}" + param = { restype: 'service', comp: 'properties' } + # @see #queues for the header `x-ms-version` + headers = { 'x-ms-version' => @opts[:storage_service_endpoint_api_version] } + body = @azure.rest_get_call(url, param, headers) + return unless body + body_hash = Hash.from_xml(body) + hash_with_snakecase_keys = RecursiveMethodHelper.method_recursive(body_hash, :snakecase) + properties = hash_with_snakecase_keys['storage_service_properties'] + if properties + create_resource_methods({ queue_properties: properties }) + public_send(:queue_properties) if respond_to?(:queue_properties) + end end private + # @see AzureKeyVault#diagnostic_settings for how to use #additional_resource_properties method. + # + def activity_log_alert_filter(filter) + return unless exists? + # `additional_resource_properties` method will create a singleton method with the `property_name` + # and make api response available through this property. + additional_resource_properties( + { + property_name: 'activity_log_alert_filtered', + property_endpoint: '/providers/microsoft.insights/eventtypes/management/values', + add_subscription_id: true, + api_version: @opts[:activity_log_alert_api_version], + filter_free_text: filter, + }, + ) + end + def to_utc(datetime) # API requires times in UTC ISO8601 format. datetime.to_time.utc.iso8601 @@ -62,9 +117,9 @@ def to_utc(datetime) # This is for backward compatibility. class AzurermStorageAccount < AzureStorageAccount name 'azurerm_storage_account' - desc 'Verifies settings for an Azure Storage Account' + desc 'Verifies settings for a Azure Storage Account' example <<-EXAMPLE - describe azurerm_storage_account(resource_group: 'rg-1', name: 'sa1') do + describe azurerm_storage_account(resource_group: resource_name, name: 'default') do it { should exist } end EXAMPLE diff --git a/libraries/azure_storage_accounts.rb b/libraries/azure_storage_accounts.rb index cf16e6b3b..1d21c48a7 100644 --- a/libraries/azure_storage_accounts.rb +++ b/libraries/azure_storage_accounts.rb @@ -29,6 +29,7 @@ def initialize(opts = {}) # @see https://github.com/inspec/inspec/blob/master/docs/dev/filtertable-usage.md table_schema = [ { column: :names, field: :name }, + { column: :ids, field: :id }, { column: :type, field: :type }, { column: :location, field: :location }, { column: :tags, field: :tags }, diff --git a/test/integration/verify/controls/azure_storage_account.rb b/test/integration/verify/controls/azure_storage_account.rb index 59be3ba61..6970ca938 100644 --- a/test/integration/verify/controls/azure_storage_account.rb +++ b/test/integration/verify/controls/azure_storage_account.rb @@ -5,6 +5,8 @@ describe azure_storage_account(resource_group: resource_group, name: storage_account) do it { should exist } it { should have_encryption_enabled } + it { should_not have_recently_generated_access_key } its('properties') { should have_attributes(supportsHttpsTrafficOnly: true) } + its('queues.enumeration_results.service_endpoint') { should include(storage_account) } end end diff --git a/test/unit/resources/azure_storage_account_test.rb b/test/unit/resources/azure_storage_account_test.rb new file mode 100644 index 000000000..8b0b271bf --- /dev/null +++ b/test/unit/resources/azure_storage_account_test.rb @@ -0,0 +1,17 @@ +require_relative 'helper' +require 'azure_storage_account' + +class AzureStorageAccountConstructorTest < Minitest::Test + def test_empty_param_not_ok + assert_raises(ArgumentError) { AzureStorageAccount.new } + end + + # resource_provider should not be allowed. + def test_resource_provider_not_ok + assert_raises(ArgumentError) { AzureStorageAccount.new(resource_provider: 'some_type') } + end + + def test_resource_group + assert_raises(ArgumentError) { AzureStorageAccount.new(name: 'my-name') } + end +end diff --git a/test/unit/resources/azure_storage_accounts_test.rb b/test/unit/resources/azure_storage_accounts_test.rb new file mode 100644 index 000000000..f79bd7f71 --- /dev/null +++ b/test/unit/resources/azure_storage_accounts_test.rb @@ -0,0 +1,25 @@ +require_relative 'helper' +require 'azure_storage_accounts' + +class AzureStorageAccountsConstructorTest < Minitest::Test + # resource_type should not be allowed. + def test_resource_type_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(resource_provider: 'some_type') } + end + + def tag_value_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(tag_value: 'some_tag_value') } + end + + def tag_name_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(tag_name: 'some_tag_name') } + end + + def test_resource_id_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(resource_id: 'some_id') } + end + + def test_name_not_ok + assert_raises(ArgumentError) { AzureStorageAccounts.new(name: 'some_name') } + end +end From 9f007cdd5f88eb7335868ae4c103bb1e7156caf3 Mon Sep 17 00:00:00 2001 From: Omer Demirok Date: Tue, 10 Nov 2020 09:37:36 +0000 Subject: [PATCH 6/6] Fix a typo Signed-off-by: Omer Demirok --- docs/resources/azure_storage_account.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources/azure_storage_account.md b/docs/resources/azure_storage_account.md index 2d31a6a2f..90abe5e90 100644 --- a/docs/resources/azure_storage_account.md +++ b/docs/resources/azure_storage_account.md @@ -33,7 +33,7 @@ describe azure_storage_account(resource_group: 'rg', name: 'sa') do end ``` ```ruby -describe azure_aks_cluster(resource_id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.ContainerService/managedClusters/{ClusterName}') do +describe azure_storage_account(resource_id: '/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}') do it { should exist } end ```