Skip to content

Commit

Permalink
Add security center policy resources (#311)
Browse files Browse the repository at this point in the history
* Add security_center_policiy(ies)

Signed-off-by: Omer Demirok <odemirok@chef.io>

* Make resources accept common parameters (api_version, http_client, cloud)

Signed-off-by: Omer Demirok <odemirok@chef.io>

* Fix azure_resource_groups#to_s method

Signed-off-by: Omer Demirok <odemirok@chef.io>

* Fix a typo in docs

Signed-off-by: Omer Demirok <odemirok@chef.io>
  • Loading branch information
Omer Demirok authored Oct 2, 2020
1 parent edef85e commit da55752
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 127 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ The static resources derived from the generic resources prepended with `azure_`
- [azure_public_ip](docs/resources/azure_public_ip.md)
- [azure_resource_group](docs/resources/azure_resource_group.md)
- [azure_resource_groups](docs/resources/azure_resource_groups.md)
- [azure_security_center_policies](docs/resources/azure_security_center_policies.md)
- [azure_security_center_policy](docs/resources/azure_security_center_policy.md)
- [azure_sql_database](docs/resources/azure_sql_database.md)
- [azure_sql_databases](docs/resources/azure_sql_databases.md)
- [azure_sql_server](docs/resources/azure_sql_server.md)
Expand Down
84 changes: 84 additions & 0 deletions docs/resources/azure_security_center_policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: About the azure_security_center_policies Resource
platform: azure
---

# azure_security_center_policies

Use the `azure_security_center_policies` InSpec audit resource to test properties and configuration of multiple Azure Polices.

## 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_subscriptions` resource block returns all security policies for a subscription.
```ruby
describe azure_security_center_policies do
it { should exist }
end
```
## Parameters

- This resource does not require any parameters.

## Properties

|Property | Description | Filter Criteria<superscript>*</superscript> |
|---------------|--------------------------------------------------------------------------------------|-----------------|
| ids | A list of the unique resource ids. | `id` |
| policy_names | A list of names of all the resources being interrogated. | `name` |
| properties | A list of properties for all the resources being interrogated. | `properties` |

<superscript>*</superscript> 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 Policy is Present
```ruby
describe azure_security_center_policies do
its('names') { should include 'my-policy' }
end
```
### Filter the Results to Include Only Those Policies which Include a Given String in Their Names
```ruby
describe azure_security_center_policies.where{ name.include?('production') } do
it { should exist }
end
```
## Filter the Results to Include Only Those Policies that the Log Collection is Enabled
```ruby
describe azure_security_center_policies.where{ properties[:logCollection] == 'On' } do
it { should exist }
its('count') { should eq 4 }
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_security_center_policies 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.
134 changes: 134 additions & 0 deletions docs/resources/azure_security_center_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
title: About the azure_security_center_policy Resource
platform: azure
---

# azure_security_center_policy

Use the `azure_security_center_policy` InSpec audit resource to test properties and configuration of an Azure security policy.

## 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_security_center_policy` resource block will lookup the `default` policy unless `resource_group` and `name` or the `resource_id` parameter is given.
```ruby
# The default security policy will be interrogated.
describe azure_security_center_policy do
its('name') { should cmp 'default' }
end
```
```ruby
describe azure_security_center_policy(resource_group: 'inspec-resource-group-9', name: 'example_policy') do
it { should exist }
end
```
```ruby
describe azure_security_center_policy(resource_id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/microsoft.Security/policies/{policy-name}') do
it { should exist }
end
```
## Parameters

| Name | Description |
|-----------------------------------------|-----------------------------------------------------------------------------------|
| resource_group | Azure resource group that the targeted resource resides in. `MyResourceGroup` |
| name | Name of the security policy to test. `policy-name` |
| resource_id | The unique resource ID. `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/microsoft.Security/policies/{policy-name}` |
| default_policy_api_version<superscript>*</superscript> | The endpoint api version for the `default_policy` property. The latest version will be used unless provided. |
| auto_provisioning_settings_api_version<superscript>*</superscript> | The endpoint api version for the `auto_provisioning_settings` property. The latest version will be used unless provided. |

<superscript>*</superscript> It will be ignored unless the default policy is tested.

Either one of the parameter sets can be provided for a valid query:
- `resource_id`
- `resource_group` and `name`
- `name: 'default'`: This is for backward compatibility. It is advised not to pass any parameters if the default security policy is tested.

## Properties

| Property | Description |
|---------------------------------|-------------|
| log_collection | Indicates if the log collection is enabled (`On`, `Off`). |
| pricing_tier | Cost/Feature Model under which the subscription is operating. |
| patch | Indicates if patch scanner notifications are enabled (`On`, `Off`). |
| baseline | Indicates if baseline scanner notifications are enabled (`On`, `Off`). |
| anti_malware | Indicates if anti-malware protection task notifications are enabled (`On`, `Off`). |
| network_security_groups | Indicates if network security group recommendations are enabled are enabled (`On`, `Off`). |
| web_application_firewall | Indicates if WAF protection task notifications are enabled (`On`, `Off`). |
| vulnerability_assessment | Indicates if vulnerability assessment recommendations are enabled (`On`, `Off`). |
| storage_encryption | Indicates if storage encryption recommendations are enabled (`On`, `Off`). |
| just_in_time_network_access | Indicates if just in time network access recommendations are enabled (`On`, `Off`). |
| app_whitelisting | Indicates if app whitelisting recommendations are enabled (`On`, `Off`). |
| sql_auditing | Indicates if sql auditing recommendations are enabled (`On`, `Off`). |
| sql_transparent_data_encryption | Indicates if sql transparent data encryption recommendations are enabled (`On`, `Off`). |
| notifications_enabled | Indicates if security alerts are emailed to the security contact (`true`, `false`). |
| send_security_email_to_admin | Indicates if the subscription admin will receive security alerts (`true`, `false`). |
| contact_emails | Contains a list of security email addresses. |
| contact_phone | Contains the security contact phone number. |
| default_policy<superscript>*</superscript> | This is the default set of policies monitored by Azure Security Center. |
| auto_provisioning_settings<superscript>*</superscript> | This is the default auto provisioning setting for the subscription. |

<superscript>*</superscript>Only applicable to the default security policy.

For properties applicable to all resources, such as `type`, `name`, `id`, `properties`, refer to [`azure_generic_resource`](azure_generic_resource.md#properties).

Any attribute in the response may be accessed with the key names separated by dots (`.`), eg. `properties.<attribute>`.

## Examples

### Test If Log Collection is Enabled
```ruby
describe azure_security_center_policy(resource_group: 'my-rg', name: 'my_policy') do
its('log_collection') { should cmp 'On' }
end
```
### Test If Notifications are Enabled
```ruby
describe azure_security_center_policy(resource_group: 'my-rg', name: 'my_policy') do
its('notifications_enabled') { should be true }
end
```
See [integration tests](../../test/integration/verify/controls/azurerm_security_center_policy.rb) for more examples.

## 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/).

### have_auto_provisioning_enabled

Test if auto provisioning is enabled. This can be used via the default security policy only.
```ruby
describe azure_security_center_policy do
it { should have_auto_provisioning_enabled }
end
```
### exists
```ruby
# If we expect a resource to always exist
describe azure_security_center_policy(resource_group: 'my-rg', server_name: 'my_policy') do
it { should exist }
end
# If we expect a resource to never exist
describe azure_security_center_policy(resource_group: 'my-rg', server_name: 'my_policy') 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.
2 changes: 2 additions & 0 deletions docs/resources/azurerm_security_center_policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: About the azurerm_security_center_policies Resource
platform: azure
---

> <b>WARNING</b> This resource will be deprecated in InSpec Azure Resource Pack version **2**. Please start using fully backward compatible [`azure_security_center_policies`](azure_security_center_policies.md) InSpec audit resource.
# azurerm\_security\_center\_policies

Use the `azurerm_security_center_policies` InSpec audit resource to test
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/azurerm_security_center_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: About the azurerm_security_center_policy Resource
platform: azure
---

> <b>WARNING</b> This resource will be deprecated in InSpec Azure Resource Pack version **2**. Please start using fully backward compatible [`azure_security_center_policy`](azure_security_center_policy.md) InSpec audit resource.
# azurerm\_security\_center\_policy

Use the `azurerm_security_center_policy` InSpec audit resource to test properties
Expand Down
22 changes: 12 additions & 10 deletions libraries/azure_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,14 @@ def get_api_version(provider, resource_type, api_version_status = 'latest')
provider_details = @azure.provider_details[provider.to_sym]
end

resource_type_details = provider_details[:resourceTypes].select { |rt| rt[:resourceType] == resource_type }&.first
resource_type_details = provider_details[:resourceTypes].select { |rt| rt[:resourceType].upcase == resource_type.upcase }&.first
# For some resource types the api version might be available with their parent resource.
if resource_type_details.nil? && resource_type.include?('/')
parent_resource_type = resource_type.split('/').first
resource_type_details = provider_details[:resourceTypes].select { |rt| rt[:resourceType] == parent_resource_type }&.first
resource_type_details = provider_details[:resourceTypes].select { |rt| rt[:resourceType].upcase == parent_resource_type&.upcase }&.first
end
if resource_type_details.nil? || !resource_type_details.is_a?(Hash)
Inspec::Log.warn "Couldn't get the #{api_version_status} API version for `#{provider}/#{resource_type}`. " \
Inspec::Log.warn "#{@__resource_name__}: Couldn't get the #{api_version_status} API version for `#{provider}/#{resource_type}`. " \
'Please make sure that the provider/resourceType are in the correct format, e.g. `Microsoft.Compute/virtualMachines`.'
else
# Caching provider details.
Expand Down Expand Up @@ -352,9 +352,10 @@ def get_api_version(provider, resource_type, api_version_status = 'latest')
#
# @param resource_list [Array] The list of short descriptions of resources.
# @param filter [Hash] The parameters used for the query.
# @param singular [TrueClass, FalseClass] Define whether or not the expected result is for a singular resource (default - true).
# @param singular [TrueClass, FalseClass] Define if the expected result is for a singular resource (default - true).
def validate_short_desc(resource_list, filter, singular = true)
message = "#{@__resource_name__}: #{@display_name}. Unable to get the resource short description with the provided data: #{filter}"
message = "#{@__resource_name__}: #{@display_name}."\
" Unable to get the resource short description with the provided data: #{filter}"
if resource_list.nil?
resource_fail(message)
false
Expand All @@ -369,12 +370,13 @@ def validate_short_desc(resource_list, filter, singular = true)
end
end

def validate_resource_uri
Helpers.validate_params_required(%i(add_subscription_id), @opts)
if @opts[:add_subscription_id] == true
@opts[:resource_uri] = "/subscriptions/#{@azure.credentials[:subscription_id]}/#{@opts[:resource_uri]}"
.gsub('//', '/')
def validate_resource_uri(opts = @opts)
Helpers.validate_params_required(%i(add_subscription_id), opts)
if opts[:add_subscription_id] == true
opts[:resource_uri] = "/subscriptions/#{@azure.credentials[:subscription_id]}/#{opts[:resource_uri]}"
.gsub('//', '/')
end
opts[:resource_uri]
end

def validate_resource_provider
Expand Down
2 changes: 1 addition & 1 deletion libraries/azure_resource_groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def initialize(opts = {})
end

def to_s
super(AzurePolicyDefinitions)
super(AzureResourceGroups)
end

private
Expand Down
56 changes: 56 additions & 0 deletions libraries/azure_security_center_policies.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'azure_generic_resources'

class AzureSecurityCenterPolicies < AzureGenericResources
name 'azure_security_center_policies'
desc 'Verifies settings for Security Center'
example <<-EXAMPLE
describe azure_security_center_policies do
its('policy_names') { should include('default') }
end
EXAMPLE

attr_reader :table

def initialize(opts = {})
opts[:resource_provider] = 'Microsoft.Security/policies'

# 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`.
table_schema = [
{ column: :policy_names, field: :name },
{ column: :ids, field: :id },
{ 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(AzureSecurityCenterPolicies)
end
end

# Provide the same functionality under the old resource name.
# This is for backward compatibility.
class AzurermSecurityCenterPolicies < AzureSecurityCenterPolicies
name 'azurerm_security_center_policies'
desc 'Verifies settings for Security Center'
example <<-EXAMPLE
describe azurerm_security_center_policies do
its('policy_names') { should include('default') }
end
EXAMPLE

def initialize(opts = {})
Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureSecurityCenterPolicies.name)
super
end
end
Loading

0 comments on commit da55752

Please sign in to comment.