diff --git a/README.md b/README.md index 6ec3adb76..407987fc1 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,8 @@ The static resources derived from the generic resources prepended with `azure_` - [azure_postgresql_server](docs/resources/azure_postgresql_server.md) - [azure_postgresql_servers](docs/resources/azure_postgresql_servers.md) - [azure_public_ip](docs/resources/azure_public_ip.md) +- [azure_sql_server](docs/resources/azure_sql_server.md) +- [azure_sql_servers](docs/resources/azure_sql_servers.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) @@ -353,7 +355,7 @@ The common parameters are: See [azure_virtual_machine](libraries/azure_virtual_machine.rb) for a standard singular resource and how to create static methods from resource properties. - If it is beneficial to accept the resource name with a more specific keyword, such as `server_name`, see [azure_mysql_server](libraries/azure_mysql_server.rb). - If a resource exists in another resource, such as a subnet on a virtual network, see [azure_subnet](libraries/azure_subnet.rb). -- If it is necessary to make an additional API call within a static method, the `get_resource` should be used. See [azure_key_vault](libraries/azure_key_vault.rb). +- If it is necessary to make an additional API call within a static method, the `create_additional_properties` should be used. See [azure_key_vault](libraries/azure_key_vault.rb). ### Plural Resources diff --git a/docs/resources/azure_sql_server.md b/docs/resources/azure_sql_server.md new file mode 100644 index 000000000..1d2ef11d7 --- /dev/null +++ b/docs/resources/azure_sql_server.md @@ -0,0 +1,123 @@ +--- +title: About the azure_sql_server Resource +platform: azure +--- + +# azure_sql_server + +Use the `azure_sql_server` InSpec audit resource to test properties and configuration of an Azure SQL Server. + +## 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` or the `resource_id` must be given as a parameter. +```ruby +describe azure_sql_server(resource_group: 'inspec-resource-group-9', name: 'example_server') do + it { should exist } +end +``` +```ruby +describe azure_sql_server(resource_id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Sql/servers/{serverName}') do + it { should exist } +end +``` +## Parameters + +| Name | Description | +|--------------------------------|-----------------------------------------------------------------------------------| +| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` | +| name | Name of the SQL server to test. `MyServer` | +| server_name | Alias for the `name` parameter. | +| resource_id | The unique resource ID. `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Sql/servers/{serverName}` | + +Either one of the parameter sets can be provided for a valid query: +- `resource_id` +- `resource_group` and `name` +- `resource_group` and `server_name` + +## Properties + +| Property | Description | +|---------------------------|-------------| +| firewall_rules | A list of all firewall rules in the targeted server with [these](https://docs.microsoft.com/en-us/rest/api/sql/firewallrules/listbyserver#firewallrulelistresult) properties. | +| administrators | A list of all administrators for the targeted server with [these](https://docs.microsoft.com/en-us/rest/api/sql/serverazureadadministrators/listbyserver#serverazureadadministrator) properties. | +| encryption_protector | A list of all encryption protectors for the targeted server with [these](https://docs.microsoft.com/en-us/rest/api/sql/encryptionprotectors/listbyserver#encryptionprotector) properties. | +| auditing_settings | Auditing settings for the targeted server with [these](https://docs.microsoft.com/en-us/rest/api/sql/server%20auditing%20settings/listbyserver#serverblobauditingpolicylistresult) properties. | +| threat_detection_settings | Threat detection settings for the targeted server with [these](https://docs.microsoft.com/en-us/rest/api/sql/databasethreatdetectionpolicies/get#databasesecurityalertpolicy) properties. | +| sku | The SKU (pricing tier) of the server. | + +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/sql/servers/get#server) for other properties available. +Any attribute in the response may be accessed with the key names separated by dots (`.`), eg. `properties.`. + +## Examples + +### Test If a SQL Server is Referenced with a Valid Name +```ruby +describe azure_sql_server(resource_group: 'my-rg', name: 'sql-server-1') do + it { should exist } +end +``` +### Test If a SQL Server is Referenced with an Invalid Name +```ruby +describe azure_sql_server(resource_group: 'my-rg', name: 'i-dont-exist') do + it { should_not exist } +end +``` +### Test If a SQL Server Has Firewall Rules Set +```ruby +describe azure_sql_server(resource_group: 'my-rg', name: 'my-server') do + its('firewall_rules') { should_not be_empty } +end +``` +### Test a SQL Server's Location and Kind +```ruby +describe azure_sql_server(resource_id: '/subscriptions/.../my-server') do + its('kind') { should cmp 'v12.0' } + its('location') { should cmp 'westeurope' } +end +``` +### Test a SQL Server's Auditing Settings +```ruby +describe azure_sql_server(resource_group: 'my-rg', name: 'my-server') do + its('auditing_settings.properties.state') { should cmp 'Disabled' } + its('auditing_settings.properties.retentionDays') { should be 0 } + its('auditing_settings.properties.isStorageSecondaryKeyInUse') { should be false } + its('auditing_settings.properties.isAzureMonitorTargetEnabled') { should be false } +end +``` +## Matchers + +This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [Universal Matchers page](/inspec/matchers/). + +### exists +```ruby +# If we expect a resource to always exist +describe azure_sql_server(resource_group: 'my-rg', server_name: 'server-name-1') do + it { should exist } +end +# If we expect a resource to never exist +describe azure_sql_server(resource_group: 'my-rg', server_name: 'server-name-1') 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_sql_servers.md b/docs/resources/azure_sql_servers.md new file mode 100644 index 000000000..91af6eb74 --- /dev/null +++ b/docs/resources/azure_sql_servers.md @@ -0,0 +1,100 @@ +--- +title: About the azure_sql_servers Resource +platform: azure +--- + +# azure_sql_servers + +Use the `azure_sql_servers` InSpec audit resource to test properties and configuration of multiple Azure SQL Servers. + +## 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 + +An `azure_sql_servers` resource block returns all Azure SQL Servers, either within a Resource Group (if provided), or within an entire Subscription. +```ruby +describe azure_sql_servers do + it { should exist } +end +``` +or +```ruby +describe azure_sql_servers(resource_group: 'my-rg') do + it { should exist } +end +``` +## Parameters + +- `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` | +| kinds | A list of kinds of all the resources being interrogated. | `kind` | +| tags | A list of `tag:value` pairs defined on the resources. | `tags` | +| skus | A list of the SKUs (pricing tiers) of the servers. | `sku` | +| types | A list of the types of resources being interrogated. | `type` | +| properties | A list of properties for all the resources being interrogated. | `properties` | + +* For information on how to use filter criteria on plural resources refer to [FilterTable usage](https://github.com/inspec/inspec/blob/master/docs/dev/filtertable-usage.md#a-where-method-you-can-call-with-hash-params-with-loose-matching). + +## Examples + +### Check a Specific SQL Server is Present +```ruby +describe azure_sql_servers do + its('names') { should include 'my-server-name' } +end +``` +### Filters the Results to Include Only Those Servers which Include the Given Name (Client Side Filtering) +```ruby +describe azure_sql_servers.where{ name.include?('production') } do + it { should exist } +end +``` +## Filters the Results to Include Only Those Servers which Reside in a Given Location (Client Side Filtering) +```ruby +describe azure_sql_servers.where{ location.eql?('westeurope') } do + it { should exist } +end +``` +## Filters the Results to Include Only Those Servers which Reside in a Given Location and Include the Given Name (Server Side Filtering - Recommended) +```ruby +describe azure_generic_resources(resource_provider: 'Microsoft.Sql/servers', substring_of_name: 'production', location: 'westeurope') do + it {should exist} +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 +describe azure_sql_servers do + it { should 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/azurerm_sql_server.md b/docs/resources/azurerm_sql_server.md index 8ae2937d5..a08b77622 100644 --- a/docs/resources/azurerm_sql_server.md +++ b/docs/resources/azurerm_sql_server.md @@ -3,6 +3,8 @@ title: About the azurerm_sql_server Resource platform: azure --- +> WARNING This resource will be deprecated in InSpec Azure Resource Pack version **2**. Please start using fully backward compatible [`azure_sql_server`](azure_sql_server.md) InSpec audit resource. + # azurerm\_sql\_server Use the `azurerm_sql_server` InSpec audit resource to test properties and configuration of diff --git a/docs/resources/azurerm_sql_servers.md b/docs/resources/azurerm_sql_servers.md index 8a3eacc7a..1e6975d03 100644 --- a/docs/resources/azurerm_sql_servers.md +++ b/docs/resources/azurerm_sql_servers.md @@ -3,6 +3,8 @@ title: About the azurerm_sql_servers Resource platform: azure --- +> WARNING This resource will be deprecated in InSpec Azure Resource Pack version **2**. Please start using fully backward compatible [`azure_sql_servers`](azure_sql_servers.md) InSpec audit resource. + # azurerm\_sql\_servers Use the `azurerm_sql_servers` InSpec audit resource to test properties and configuration of Azure SQL Servers. diff --git a/libraries/azure_generic_resource.rb b/libraries/azure_generic_resource.rb index ab44e0c95..63af731a4 100644 --- a/libraries/azure_generic_resource.rb +++ b/libraries/azure_generic_resource.rb @@ -144,4 +144,23 @@ def resource_group def failed_resource? @failed_resource ||= false end + + # Create properties on a resource acquired via additional API call in a static method. + # @param opts [Hash] + # property_name [string] The name of the property. + # property_endpoint [string] The URI of the properties. + # E.g., '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/ + # Microsoft.Sql/servers/{serverName}/firewallRules'. + # api_version [string] The api version of the endpoint (default - latest). + def additional_resource_properties(opts = {}) + Helpers.validate_parameters(resource_name: @__resource_name__, + required: %i(property_name property_endpoint), + allow: %i(api_version), + opts: opts) + opts[:api_version] = 'latest' unless opts.key?(:api_version) + properties = get_resource({ resource_uri: opts[:property_endpoint], api_version: opts[:api_version] }) + properties = properties[:value] if properties.key?(:value) + create_resource_methods({ opts[:property_name].to_sym => properties }) + public_send(opts[:property_name].to_sym) if respond_to?(opts[:property_name]) + end end diff --git a/libraries/azure_key_vault.rb b/libraries/azure_key_vault.rb index f109601cd..7d3a8bc6c 100644 --- a/libraries/azure_key_vault.rb +++ b/libraries/azure_key_vault.rb @@ -66,22 +66,22 @@ def to_s # resource uri is the same as (resource) `id` of the key vault. # @see: https://docs.microsoft.com/en-us/rest/api/monitor/diagnosticsettings/list # - # `#get_resource` method will be used to get the diagnostic settings from the Rest API. - # api_version => the api_version for the microsoft.insights/diagnosticSettings - # resource_uri => id + '/providers/microsoft.insights/diagnosticSettings' + # `#additional_resource_properties` method will be used to get the diagnostic settings from the Rest API. + # property_name => The name of the properties, `diagnostic_settings`. + # property_endpoint => id + '/providers/microsoft.insights/diagnosticSettings' + # api_version => The api_version for the microsoft.insights/diagnosticSettings + # If not provided the `latest` version will be used. (RECOMMENDED) # def diagnostic_settings return unless exists? - if @diagnostic_settings.nil? - resource_uri = id + '/providers/microsoft.insights/diagnosticSettings' - api_query_diagnostic_settings = { - resource_uri: resource_uri, - # api_version is fixed due to this operation is not supported by other versions. + # `api_version` is fixed for backward compatibility. + additional_resource_properties( + { + property_name: 'diagnostic_settings', + property_endpoint: id + '/providers/microsoft.insights/diagnosticSettings', api_version: '2017-05-01-preview', - } - # The `:value` will return the diagnostic settings. - @diagnostic_settings = get_resource(api_query_diagnostic_settings)[:value] - end + }, + ) end end diff --git a/libraries/azure_mariadb_server.rb b/libraries/azure_mariadb_server.rb index fe68b32e3..61034921e 100644 --- a/libraries/azure_mariadb_server.rb +++ b/libraries/azure_mariadb_server.rb @@ -30,15 +30,16 @@ def to_s # Following methods are created to provide the same functionality with the current resource pack >>>> # @see https://github.com/inspec/inspec-azure - # @see AzureKeyVault#diagnostic_settings for how to use #getresource method. + # @see AzureKeyVault#diagnostic_settings for how to use #additional_resource_properties method. + # def firewall_rules return unless exists? - resource_uri = id + '/firewallRules' - api_query_for_firewall = { - resource_uri: resource_uri, - } - # The `:value` will return the data. - @firewall_rules ||= get_resource(api_query_for_firewall)[:value] + additional_resource_properties( + { + property_name: 'firewall_rules', + property_endpoint: id + '/firewallRules', + }, + ) end end diff --git a/libraries/azure_mysql_server.rb b/libraries/azure_mysql_server.rb index 1076ea116..594ade9a8 100644 --- a/libraries/azure_mysql_server.rb +++ b/libraries/azure_mysql_server.rb @@ -62,15 +62,16 @@ def to_s # GET https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/ # Microsoft.DBforMySQL/servers/{serverName}/firewallRules?api-version=2017-12-01 # - # #getresource method + # @see AzureKeyVault#diagnostic_settings for how to use #additional_resource_properties method. # def firewall_rules return unless exists? - resource_uri = id + '/firewallRules' - api_query_for_firewall = { - resource_uri: resource_uri, - } - @firewall_rules ||= get_resource(api_query_for_firewall)[:value] + additional_resource_properties( + { + property_name: 'firewall_rules', + property_endpoint: id + '/firewallRules', + }, + ) end end diff --git a/libraries/azure_sql_server.rb b/libraries/azure_sql_server.rb new file mode 100644 index 000000000..579654fcf --- /dev/null +++ b/libraries/azure_sql_server.rb @@ -0,0 +1,101 @@ +require 'azure_generic_resource' + +class AzureSqlServer < AzureGenericResource + name 'azure_sql_server' + desc 'Verifies settings for an Azure SQL Server' + example <<-EXAMPLE + describe azure_sql_server(resource_group: 'rg-1', name: 'my-server-name') do + it { should exist } + end + EXAMPLE + + 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.Sql/servers', opts) + + opts[:resource_identifiers] = %i(server_name) + + # static_resource parameter must be true for setting the resource_provider in the backend. + super(opts, true) + end + + def to_s + super(AzureSqlServer) + 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 + + # @see AzureKeyVault#diagnostic_settings for how to use #additional_resource_properties method. + # + def firewall_rules + return unless exists? + additional_resource_properties( + { + property_name: 'firewall_rules', + property_endpoint: id + '/firewallRules', + }, + ) + end + + def auditing_settings + return unless exists? + additional_resource_properties( + { + property_name: 'auditing_settings', + property_endpoint: id + '/auditingSettings/default', + }, + ) + end + + def threat_detection_settings + return unless exists? + additional_resource_properties( + { + property_name: 'threat_detection_settings', + property_endpoint: id + '/securityAlertPolicies/Default', + }, + ) + end + + def administrators + return unless exists? + additional_resource_properties( + { + property_name: 'administrators', + property_endpoint: id + '/administrators', + }, + ) + end + + def encryption_protector + return unless exists? + additional_resource_properties( + { + property_name: 'encryption_protector', + property_endpoint: id + '/encryptionProtector', + }, + ) + end +end + +# Provide the same functionality under the old resource name. +# This is for backward compatibility. +class AzurermSqlServer < AzureSqlServer + name 'azurerm_sql_server' + desc 'Verifies settings for an Azure SQL Server' + example <<-EXAMPLE + describe azurerm_sql_server(resource_group: 'rg-1', server_name: 'my-server-name') do + it { should exist } + end + EXAMPLE + + def initialize(opts = {}) + Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureSqlServer.name) + super + end +end diff --git a/libraries/azure_sql_servers.rb b/libraries/azure_sql_servers.rb new file mode 100644 index 000000000..c3c147344 --- /dev/null +++ b/libraries/azure_sql_servers.rb @@ -0,0 +1,65 @@ +require 'azure_generic_resources' + +class AzureSqlServers < AzureGenericResources + name 'azure_sql_servers' + desc 'Verifies settings for a collection of Azure SQL Servers' + example <<-EXAMPLE + describe azure_sql_servers 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.Sql/servers', 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: :skus, field: :sku }, + { column: :kinds, field: :kind }, + { column: :ids, field: :id }, + { column: :tags, field: :tags }, + { column: :types, field: :type }, + { column: :locations, field: :location }, + { column: :properties, field: :properties }, + ] + + # 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(AzureSqlServers) + end +end + +# Provide the same functionality under the old resource name. +# This is for backward compatibility. +class AzurermSqlServers < AzureSqlServers + name 'azurerm_sql_servers' + desc 'Verifies settings for a collection of Azure SQL Servers' + example <<-EXAMPLE + describe azurerm_sql_servers do + it { should exist } + end + EXAMPLE + + def initialize(opts = {}) + Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureSqlServers.name) + super + end +end diff --git a/libraries/azurerm_sql_server.rb b/libraries/azurerm_sql_server.rb deleted file mode 100644 index 04eed63c1..000000000 --- a/libraries/azurerm_sql_server.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true - -require 'azurerm_resource' - -class AzurermSqlServer < AzurermSingularResource - name 'azurerm_sql_server' - desc 'Verifies settings for an Azure SQL Server' - example <<-EXAMPLE - describe azure_sql_server(resource_group: 'rg-1', server_name: 'my-server-name') do - it { should exist } - end - EXAMPLE - - ATTRS = %i( - id - name - kind - location - type - tags - properties - ).freeze - - attr_reader(*ATTRS) - - def initialize(resource_group: nil, server_name: nil) - sql_server = management.sql_server(resource_group, server_name) - return if has_error?(sql_server) - - assign_fields(ATTRS, sql_server) - - @resource_group = resource_group - @server_name = server_name - @exists = true - end - - def auditing_settings - @auditing_settings ||= management.sql_server_auditing_settings(@resource_group, @server_name) - end - - def threat_detection_settings - @threat_detection_settings ||= management.sql_server_threat_detection_settings(@resource_group, @server_name) - end - - def administrators - @administrators ||= management.sql_server_administrators(@resource_group, @server_name) - end - - def encryption_protector - @encryption_protector ||= management.sql_encryption_protector(@resource_group, @server_name) - end - - def firewall_rules - @firewall_rules ||= management.sql_server_firewall_rules(@resource_group, @server_name) - end - - def to_s - "Azure SQL Server: '#{name}'" - end -end diff --git a/libraries/azurerm_sql_servers.rb b/libraries/azurerm_sql_servers.rb deleted file mode 100644 index 3996440c3..000000000 --- a/libraries/azurerm_sql_servers.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -require 'azurerm_resource' -require 'json' - -class AzurermSqlServers < AzurermPluralResource - name 'azurerm_sql_servers' - desc 'Verifies settings for a collection of Azure SQL Servers' - example <<-EXAMPLE - describe azurerm_sql_servers do - it { should exist } - end - EXAMPLE - - attr_reader :table - - FilterTable.create - .register_column(:ids, field: :id) - .register_column(:names, field: :name) - .register_column(:kinds, field: :kind) - .register_column(:locations, field: :location) - .register_column(:properties, field: :properties) - .register_column(:tags, field: :tag) - .register_column(:types, field: :type) - .install_filter_methods_on_resource(self, :table) - - def initialize(resource_group: nil) - servers = management.sql_servers(resource_group) - return if has_error?(servers) - - @table = servers - end - - def to_s - 'Azure SQL Servers' - end -end diff --git a/libraries/backend/azure_connection.rb b/libraries/backend/azure_connection.rb index 88f01b6f7..f0387e524 100644 --- a/libraries/backend/azure_connection.rb +++ b/libraries/backend/azure_connection.rb @@ -161,10 +161,10 @@ def fail_api_query(resp, message = nil) message += resp.body.to_s if code.nil? end resource_not_found_codes = %w{Request_ResourceNotFound ResourceGroupNotFound ResourceNotFound NotFound} - wrong_api_keyword = 'The supported api-versions are' + wrong_api_keyword = ['The supported api-versions are', 'The supported versions'] invalid_api_codes = %w{InvalidApiVersionParameter NoRegisteredProviderFound InvalidResourceType} if code - if invalid_api_codes.include?(code) && error_message&.include?(wrong_api_keyword) + if invalid_api_codes.include?(code) && wrong_api_keyword.any? { |kw| error_message&.include?(kw) } raise UnsuccessfulAPIQuery::UnexpectedHTTPResponse::InvalidApiVersionParameter, error_message elsif resource_not_found_codes.include?(code) raise UnsuccessfulAPIQuery::ResourceNotFound, error_message diff --git a/terraform/azure.tf b/terraform/azure.tf index 93fd312b1..469c4e729 100644 --- a/terraform/azure.tf +++ b/terraform/azure.tf @@ -919,7 +919,7 @@ resource "azurerm_cosmosdb_account" "inspectest_cosmosdb" { } geo_location { - prefix = "inspectest-geo-prefix" + prefix = "inspectest-geo-prefix-${random_string.cosmo_db.result}" location = azurerm_resource_group.rg.location failover_priority = 0 } diff --git a/test/integration/verify/controls/azurerm_cosmosdb_database_account.rb b/test/integration/verify/controls/azurerm_cosmosdb_database_account.rb index cd4c0b641..12599cfac 100644 --- a/test/integration/verify/controls/azurerm_cosmosdb_database_account.rb +++ b/test/integration/verify/controls/azurerm_cosmosdb_database_account.rb @@ -2,6 +2,7 @@ cosmosdb_database_account = attribute('cosmosdb_database_account', default: nil) control 'azurerm_cosmosdb_database_account' do + only_if { !cosmosdb_database_account.nil? } describe azurerm_cosmosdb_database_account(resource_group: resource_group, cosmosdb_database_account: cosmosdb_database_account) do its('name') { should eq cosmosdb_database_account } diff --git a/test/integration/verify/controls/azurerm_sql_servers.rb b/test/integration/verify/controls/azurerm_sql_servers.rb index d60389fc9..bdb4f94ae 100644 --- a/test/integration/verify/controls/azurerm_sql_servers.rb +++ b/test/integration/verify/controls/azurerm_sql_servers.rb @@ -5,7 +5,13 @@ only_if { !sql_server_name.nil? } describe azurerm_sql_servers(resource_group: resource_group) do - it { should exist } + it { should exist } its('names') { should include sql_server_name } end + + azure_sql_servers.ids.each do |id| + describe azure_sql_server(resource_id: id) do + it { should exist } + end + end end diff --git a/test/unit/resources/azure_sql_server_test.rb b/test/unit/resources/azure_sql_server_test.rb new file mode 100644 index 000000000..db2b0331d --- /dev/null +++ b/test/unit/resources/azure_sql_server_test.rb @@ -0,0 +1,17 @@ +require_relative 'helper' +require 'azure_sql_server' + +class AzureSqlServerConstructorTest < Minitest::Test + def test_empty_param_not_ok + assert_raises(ArgumentError) { AzureSqlServer.new } + end + + # resource_provider should not be allowed. + def test_resource_provider_not_ok + assert_raises(ArgumentError) { AzureSqlServer.new(resource_provider: 'some_type') } + end + + def test_resource_group + assert_raises(ArgumentError) { AzureSqlServer.new(name: 'my-name') } + end +end diff --git a/test/unit/resources/azure_sql_servers_test.rb b/test/unit/resources/azure_sql_servers_test.rb new file mode 100644 index 000000000..95718490f --- /dev/null +++ b/test/unit/resources/azure_sql_servers_test.rb @@ -0,0 +1,25 @@ +require_relative 'helper' +require 'azure_sql_servers' + +class AzureSqlServersConstructorTest < Minitest::Test + # resource_type should not be allowed. + def test_resource_type_not_ok + assert_raises(ArgumentError) { AzureSqlServers.new(resource_provider: 'some_type') } + end + + def tag_value_not_ok + assert_raises(ArgumentError) { AzureSqlServers.new(tag_value: 'some_tag_value') } + end + + def tag_name_not_ok + assert_raises(ArgumentError) { AzureSqlServers.new(tag_name: 'some_tag_name') } + end + + def test_resource_id_not_ok + assert_raises(ArgumentError) { AzureSqlServers.new(resource_id: 'some_id') } + end + + def test_name_not_ok + assert_raises(ArgumentError) { AzureSqlServers.new(name: 'some_name') } + end +end