Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add management_group resources #332

Merged
merged 6 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ The static resources derived from the generic resources prepended with `azure_`
- [azure_load_balancers](docs/resources/azure_load_balancers.md)
- [azure_lock](docs/resources/azure_lock.md)
- [azure_locks](docs/resources/azure_locks.md)
- [azure_management_group](docs/resources/azure_management_group.md)
- [azure_management_groups](docs/resources/azure_management_groups.md)
- [azure_mariadb_server](docs/resources/azure_mariadb_server.md)
- [azure_mariadb_servers](docs/resources/azure_mariadb_servers.md)
- [azure_monitor_activity_log_alert](docs/resources/azure_monitor_activity_log_alert.md)
Expand Down
6 changes: 3 additions & 3 deletions docs/resources/azure_aks_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ Either one of the parameter sets can be provided for a valid query:
|-----------------------|-------------|
| identity | The identity of the managed cluster, if configured. It is a [managed cluster identity object](https://docs.microsoft.com/en-us/rest/api/aks/managedclusters/get#managedclusteridentity). |
| sku | The SKU (pricing tier) of the resource. |
| diagnostic_settings | The diagnostic settings for the resource group that the AKS cluster is within |
| enabled_logging_types | The logging types that are enabled for the AKS cluster |
| disabled_logging_types| The logging types that are disabled for the AKS cluster |
| diagnostic_settings | The diagnostic settings for the resource group that the AKS cluster is within. |
| enabled_logging_types | The logging types that are enabled for the AKS cluster. |
| disabled_logging_types| The logging types that are disabled for the AKS cluster. |

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

Expand Down
103 changes: 103 additions & 0 deletions docs/resources/azure_management_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
title: About the azure_management_group Resource
platform: azure
---

# azure_management_group

Use the `azure_management_group` InSpec audit resource to test properties of an Azure management group.

## 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_management_group` resource block identifies a management group by its `name` or the `resource_id`.
```ruby
describe azure_management_group(name: 'abcd-1234') do
it { should exist }
end
```
```ruby
describe azure_management_group(resource_id: '/providers/Microsoft.Management/managementGroups/{groupId}') do
it { should exist }
end
```
## Parameters

| Name | Description |
|--------------------------------|-----------------------------------------------------------------------------------|
| name | Management group name. `20000000-0001-0000-0000-000000000000` |
| group_id | Alias for the `name` parameter. |
| resource_id | The unique resource ID. `/providers/Microsoft.Management/managementGroups/{groupId}` |
| expand | Optional. The `expand: 'children'` includes children in the response. `expand: 'path'` includes the path from the root group to the current group. |
| recurse | Optional. The `recurse: true` includes the entire hierarchy in the response. Note that `expand: 'children'` will be set if `recurse` is set to `true`. |
| filter | Optional. A filter which allows the exclusion of subscriptions from results (i.e. `filter: 'children.childType ne Subscription'`) |

Either one of the parameter sets can be provided for a valid query along with the optional parameters:
- `resource_id`
- `name`
- `group_id`

## Properties

| Property | Description |
|------------------------|-------------|
| tenant_id | The management group tenant id. |
| parent_name | The management group parent name. |
| parent_id | The management group parent resource id. `/providers/Microsoft.Management/managementGroups/{groupId}` |
| children_display_names | The list of management group children display names. |
| children_ids | The list of management group children ids. |
| children_names | The list of management group children names. |
| children_types | The list of management group children types. |

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/resources/managementgroups/get#managementgroup) for other properties available.
Any attribute in the response may be accessed with the key names separated by dots (`.`).

## Examples

### Test Tenant ID, Parent Name, Children Display Name
```ruby
describe azure_management_group(group_id: 'abc-1234', recurse: true, expand: 'children') do
its('tenant_id') { should eq('00000000-0000-0000-0000-000000000000') }
its('parent_name') { should eq('MyGroupsParentName') }
its('children_display_names') { should include('I am a child of the group!') }
end
```
See [integration tests](../../test/integration/verify/controls/azurerm_management_group.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://docs.chef.io/inspec/matchers/).

### exists
```ruby
# If we expect a resource to always exist
describe azure_management_group(name: 'abcd-1234') do
it { should exist }
end

# If we expect a resource to never exist
describe azure_management_group(name: 'abcd-1234') 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.
78 changes: 78 additions & 0 deletions docs/resources/azure_management_groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
title: About the azure_management_groups Resource
platform: azure
---

# azure_management_groups

Use the `azure_management_groups` InSpec audit resource to test properties and configuration of multiple Azure management groups.

## 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_management_groups` resource block returns management groups for the authenticated user.
```ruby
describe azure_management_groups do
#...
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` |
| names | A list of names of all the resources being interrogated. | `name` |
| types | A list of types of all the resources being interrogated. | `type` |
| 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

### Test that a Named Management Group Exist
```ruby
describe azure_management_groups do
its('names') { should include('abcd-1234') }
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 management group to exist
describe azure_management_groups do
it { should exist }
end

# If we expect zero matches
describe azure_management_groups 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_management_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: About the azurerm_management_group 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_management_group`](azure_management_group.md) InSpec audit resource.

# azurerm\_management\_group

Use the `azurerm_management_group` InSpec audit resource to test properties related to a
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/azurerm_management_groups.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: About the azurerm_management_groups 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_management_groups`](azure_management_groups.md) InSpec audit resource.

# azurerm\_management\_groups

Use the `azurerm_management_groups` InSpec audit resource to test properties related to
Expand Down
3 changes: 2 additions & 1 deletion libraries/azure_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ def validate_short_desc(resource_list, filter, singular = true)
end

def validate_resource_uri(opts = @opts)
opts[:resource_uri].prepend('/') unless opts[:resource_uri].start_with?('/')
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]}"
Expand Down Expand Up @@ -424,7 +425,7 @@ def get_next_link(next_link)
def specific_resource_constraint(resource_provider, opts)
if opts.is_a?(Hash)
parameter_blacklist = %i(allowed_parameters required_parameters resource_uri resource_provider display_name
tag_name tag_value add_subscription_id resource_type)
tag_name tag_value add_subscription_id resource_type query_parameters)
if opts.keys.any? { |key| parameter_blacklist.include?(key) }
raise ArgumentError, "#{@__resource_name__}: The following parameters are not allowed: "\
"#{parameter_blacklist}"
Expand Down
6 changes: 5 additions & 1 deletion libraries/azure_generic_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def initialize(opts = {}, static_resource = false)
# Use the latest api_version unless provided.
api_version = @opts[:api_version] || 'latest'
query_parameters = { 'api-version' => api_version }
@opts[:query_parameters]&.each do |k, v|
query_parameters.merge!({ k => v })
end
catch_failed_resource_queries do
params = { resource_uri: @resource_id, query_parameters: query_parameters }
@resource_long_desc = get_resource(params)
Expand Down Expand Up @@ -117,7 +120,8 @@ def additional_resource_properties(opts = {})
def validate_static_resource
required_parameters = %i(resource_group resource_provider name)
required_parameters += @opts[:required_parameters] if @opts.key?(:required_parameters)
allowed_parameters = %i(resource_path resource_identifiers resource_id resource_uri add_subscription_id)
allowed_parameters = %i(resource_path resource_identifiers resource_id resource_uri add_subscription_id
query_parameters)
allowed_parameters += @opts[:allowed_parameters] if @opts.key?(:allowed_parameters)

if @opts.key?(:resource_id)
Expand Down
130 changes: 130 additions & 0 deletions libraries/azure_management_group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
require 'azure_generic_resource'

class AzureManagementGroup < AzureGenericResource
name 'azure_management_group'
desc 'Verifies settings for an Azure Management Group'
example <<-EXAMPLE
describe azure_management_group(group_id: 'example-group') 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.Management/managementGroups', opts)
opts[:resource_uri] = "providers/#{opts[:resource_provider]}"
opts[:add_subscription_id] = false
opts[:resource_identifiers] = %i(group_id)
opts[:allowed_parameters] = %i(expand recurse filter)
# For backward compatibility.
opts[:query_parameters] = {
'$recurse' => opts[:recurse] || false,
}
opts[:query_parameters].merge!('$expand' => opts[:expand]) unless opts[:expand].nil?
# Note that $expand=children must be passed up if $recurse is set to true.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code answers my question... I think the wording should be changed slightly. $expand=children must be set if $recurse is set to true.
OR
$expand=children will be set if $recurse is set to true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this comment also be updated for consistency?

if opts[:query_parameters]['$recurse']
opts[:query_parameters]['$expand'] = 'children'
end
opts[:query_parameters].merge!('$filter' => opts[:filter]) unless opts[:filter].nil?

# static_resource parameter must be true for setting the resource_provider in the backend.
super(opts, true)
end

def to_s
super(AzureManagementGroup)
end

# For backward compatibility
def display_name
return unless exists?
properties&.displayName
end

def children
return unless exists?
properties&.children
end

def roles
return unless exists?
properties&.roles
end

def tenant_id
return unless exists?
properties&.tenantId
end

def parent
return unless exists?
properties&.details&.parent
end

def parent_name
return unless exists?
properties&.details&.parent&.name
end

def parent_id
return unless exists?
properties&.details&.parent&.id
end

def parent_display_name
return unless exists?
properties&.details&.parent&.displayName
end

def children_display_names
return unless exists?
return [] if children.nil?
Array(children).map(&:displayName)
end

def children_ids
return unless exists?
return [] if children.nil?
Array(children).map(&:id)
end

def children_names
return unless exists?
return [] if children.nil?
Array(children).map(&:name)
end

def children_roles
return unless exists?
return [] if children.nil?
Array(children).map(&:roles)
end

def children_types
return unless exists?
return [] if children.nil?
Array(children).map(&:type)
end
end

# Provide the same functionality under the old resource name.
# This is for backward compatibility.
class AzurermManagementGroup < AzureManagementGroup
name 'azurerm_management_group'
desc 'Verifies settings for an Azure Management Group'
example <<-EXAMPLE
describe azurerm_management_group(group_id: 'example-group') 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)

Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureManagementGroup.name)
super
end
end
Loading