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

RESOURCE-103 Support azure synapse workspaces #601

Merged
merged 11 commits into from
Mar 12, 2022
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,8 @@ The following is a list of static resources.
- [azure_subscriptions](docs/resources/azure_subscriptions.md)
- [azure_synapse_notebook](docs/resources/azure_synapse_notebook.md)
- [azure_synapse_notebooks](docs/resources/azure_synapse_notebooks.md)
- [azure_synapse_workspace](docs/resources/azure_synapse_workspace.md)
- [azure_synapse_workspaces](docs/resources/azure_synapse_workspaces.md)
- [azure_virtual_machine](docs/resources/azure_virtual_machine.md)
- [azure_virtual_machines](docs/resources/azure_virtual_machines.md)
- [azure_virtual_machine_disk](docs/resources/azure_virtual_machine_disk.md)
Expand Down
103 changes: 103 additions & 0 deletions docs-chef-io/content/inspec/resources/azure_synapse_workspace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
+++
title = "azure_synapse_workspace Resource"
platform = "azure"
draft = false
gh_repo = "inspec-azure"

[menu.inspec]
title = "azure_synapse_workspace"
identifier = "inspec/resources/azure/azure_synapse_workspace Resource"
parent = "inspec/resources/azure"
+++

Use the `azure_synapse_workspace` InSpec audit resource to test properties related to an Azure Synapse workspace.

## Azure REST API Version, Endpoint, and HTTP Client Parameters

{{% inspec_azure_common_parameters %}}

## Installation

{{% inspec_azure_install %}}

## Syntax

```ruby
describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: 'SYNAPSE_WORKSPACE_NAME') do
it { should exist }
its('type') { should eq 'Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups' }
its('location') { should eq 'eastus' }
end
```

```ruby
describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: 'SYNAPSE_WORKSPACE_NAME') do
it { should exist }
end
```

## Parameters

`name` _(required)_
: Name of the Azure Synapse workspace to test.

`resource_group` _(required)_
: Azure resource group that the targeted resource resides in.

## Properties

`id`
: Resource Id.

`name`
: Resource name.

`type`
: Resource type. `Microsoft.Synapse/workspaces`.

`location`
: The Geo-location where the resource lives.

`properties`
: The properties of the Synapse workspaces.

`properties.provisioningState`
: State of the resource.


For properties applicable to all resources, such as `type`, `name`, `id`, `properties`, refer to [`azure_generic_resource`]({{< relref "azure_generic_resource.md#properties" >}}).

Also, refer to [Azure documentation](https://docs.microsoft.com/en-us/rest/api/synapse/workspaces/get) for other properties available.

## Examples

**Test that the Synapse workspaces is provisioned successfully.**

```ruby
describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: 'SYNAPSE_WORKSPACE_NAME') do
its('properties.provisioningState') { should eq 'Succeeded' }
end
```

## Matchers

{{% inspec_matchers_link %}}

### exists

```ruby
# If a Synapse workspaces is found it will exist

describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: 'SYNAPSE_WORKSPACE_NAME') do
it { should exist }
end
# if Synapse workspaces is not found it will not exist

describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: 'SYNAPSE_WORKSPACE_NAME') do
it { should_not exist }
end
```

## Azure Permissions

{{% azure_permissions_service_principal role="reader" %}}
113 changes: 113 additions & 0 deletions docs-chef-io/content/inspec/resources/azure_synapse_workspaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
+++
title = "azure_synapse_workspaces Resource"
platform = "azure"
draft = false
gh_repo = "inspec-azure"

[menu.inspec]
title = "azure_synapse_workspaces"
identifier = "inspec/resources/azure/azure_synapse_workspaces Resource"
parent = "inspec/resources/azure"
+++

Use the `azure_synapse_workspaces` InSpec audit resource to test properties related to all Azure Synapse workspaces.

## Azure REST API Version, Endpoint, and HTTP Client Parameters

{{% inspec_azure_common_parameters %}}

## Installation

{{% inspec_azure_install %}}

## Syntax

An `azure_synapse_workspaces` resource block returns all Azure Synapse workspaces.

```ruby
describe azure_synapse_workspaces do
#...
end
```

## Parameters

`resource_group` _(optional)_
: Azure resource group that the targeted resource resides in.

## Properties

`ids`
: A list of resource IDs.

: **Field**: `id`

`names`
: A list of resource Names.

: **Field**: `name`

`types`
: A list of the resource types.

: **Field**: `type`

`properties`
: A list of Properties for all the Synapse workspaces.

: **Field**: `properties`

`locations`
: A list of the Geo-locations.

: **Field**: `location`

`provisioningStates`
: A list of provisioning states of the Synapse workspaces.

: **Field**: `provisioningState`

{{% inspec_filter_table %}}

## Examples

**Loop through Synapse workspaces by their names.**

```ruby
azure_synapse_workspaces.names.each do |name|
describe azure_synapse_workspace(resource_group: 'RESOURCE_GROUP', name: name) do
it { should exist }
end
end
```

**Test that there are Synapse workspaces that are successfully provisioned.**

```ruby
describe azure_synapse_workspaces(resource_group: 'RESOURCE_GROUP').where(provisioningState: 'Succeeded') do
it { should exist }
end
```

## Matchers

{{% inspec_matchers_link %}}

### exists

```ruby
# Should not exist if no Synapse workspaces are present

describe azure_synapse_workspaces(resource_group: 'RESOURCE_GROUP') do
it { should_not exist }
end
# Should exist if the filter returns at least one Synapse workspaces

describe azure_synapse_workspaces(resource_group: 'RESOURCE_GROUP') do
it { should exist }
end
```

## Azure Permissions

{{% azure_permissions_service_principal role="reader" %}}
22 changes: 22 additions & 0 deletions libraries/azure_synapse_workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'azure_generic_resource'

class AzureSynapseWorkspace < AzureGenericResource
name 'azure_synapse_workspace'
desc 'Retrieves and verifies the settings of an Azure Synapse Workspace.'
example <<-EXAMPLE
describe azure_synapse_workspace(resource_group: 'inspec-def-rg', name: 'synapse-ws') do
it { should exist }
end
EXAMPLE

def initialize(opts = {})
raise ArgumentError, 'Parameters must be provided in an Hash object.' unless opts.is_a?(Hash)

opts[:resource_provider] = specific_resource_constraint('Microsoft.Synapse/workspaces', opts)
super(opts, true)
end

def to_s
super(AzureSynapseWorkspace)
end
end
35 changes: 35 additions & 0 deletions libraries/azure_synapse_workspaces.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'azure_generic_resources'

class AzureSynapseWorkspaces < AzureGenericResources
name 'azure_synapse_workspaces'
desc 'Verifies settings for a collection of Azure Synapse Workspaces'
example <<-EXAMPLE
describe azure_synapse_workspaces do
it { should exist }
end
EXAMPLE

def initialize(opts = {})
raise ArgumentError, 'Parameters must be provided in an Hash object.' unless opts.is_a?(Hash)

opts[:resource_provider] = specific_resource_constraint('Microsoft.Synapse/workspaces', opts)
super(opts, true)
return if failed_resource?

populate_filter_table_from_response
end

def to_s
super(AzureSynapseWorkspaces)
end

private

def populate_table
@resources.each do |resource|
@table << resource.merge(resource[:properties])
.merge(resource.dig(:properties, :defaultDataLakeStorage))
.merge(resource.dig(:properties, :connectivityEndpoints))
end
end
end
19 changes: 19 additions & 0 deletions terraform/azure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1612,4 +1612,23 @@ resource "azurerm_data_factory_dataset_cosmosdb_sqlapi" "cosmosdb_dataset" {
data_factory_name = azurerm_data_factory.adf.name
linked_service_name = azurerm_data_factory_linked_service_mysql.dflsmsql.name
collection_name = "bar"
}

resource "azurerm_synapse_workspace" "synapse_inspec_ws" {
name = "synapse-inspec-ws"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
storage_data_lake_gen2_filesystem_id = azurerm_storage_data_lake_gen2_filesystem.inspec_adls_gen2.id
sql_administrator_login = "sqladminuser"
sql_administrator_login_password = "H@Sh1CoR3!"

aad_admin {
login = "AzureAD Admin"
object_id = "00000000-0000-0000-0000-000000000000"
tenant_id = "00000000-0000-0000-0000-000000000000"
}

tags = {
Env = "inspec"
}
}
5 changes: 5 additions & 0 deletions terraform/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,9 @@ output "inspec_sql_virtual_machine" {
output "inspec_powerbi_workspace_id" {
description = "The name of the Azure Power BI Workspace"
value = powerbi_workspace.inspec_powerbi_workspace.id
}

output "synapse_inspec_ws_name" {
description = "Synapse Workspace Name"
value = azurerm_synapse_workspace.synapse_inspec_ws.name
}
14 changes: 14 additions & 0 deletions test/integration/verify/controls/azure_synapse_workspace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource_group = input(:resource_group, value: '')
location = input(:location, value: '')
synapse_ws_name = input(:synapse_inspec_ws_name, value: '')

control 'Verify settings of all Azure Synapse Workspaces' do
describe azure_synapse_workspace(resource_group: resource_group, name: synapse_ws_name) do
it { should exist }
its('name') { should eq synapse_ws_name }
its('location') { should eq location.downcase.gsub("\s", '') }
its('properties.provisioningState') { should eq 'Succeeded' }
its('properties.managedResourceGroupName') { should eq resource_group }
its('properties.sqlAdministratorLogin') { should eq 'login' }
end
end
14 changes: 14 additions & 0 deletions test/integration/verify/controls/azure_synapse_workspaces.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource_group = input(:resource_group, value: '')
location = input(:location, value: '')
synapse_ws_name = input(:synapse_inspec_ws_name, value: '')

control 'Verify settings of all Azure Synapse Workspaces' do
describe azure_synapse_workspaces do
it { should exist }
its('names') { should include synapse_ws_name }
its('locations') { should include location.downcase.gsub("\s", '') }
its('provisioningStates') { should include 'Succeeded' }
its('managedResourceGroupNames') { should include resource_group }
its('sqlAdministratorLogins') { should include 'login' }
end
end
17 changes: 17 additions & 0 deletions test/unit/resources/azure_synapse_workspace_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require_relative 'helper'
require 'azure_synapse_workspace'

class AzureSynapseWorkspaceConstructorTest < Minitest::Test
def test_empty_param_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspace.new }
end

# resource_provider should not be allowed.
def test_resource_provider_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspace.new(resource_provider: 'some_type') }
end

def test_resource_group_name_alone_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspace.new(resource_group: 'test') }
end
end
21 changes: 21 additions & 0 deletions test/unit/resources/azure_synapse_workspaces_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require_relative 'helper'
require 'azure_synapse_workspaces'

class AzureSynapseWorkspacesConstructorTest < Minitest::Test
# resource_type should not be allowed.
def test_resource_type_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspaces.new(resource_provider: 'some_type') }
end

def tag_value_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspaces.new(tag_value: 'some_tag_value') }
end

def tag_name_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspaces.new(tag_name: 'some_tag_name') }
end

def test_name_not_ok
assert_raises(ArgumentError) { AzureSynapseWorkspaces.new(name: 'some_name') }
end
end