Skip to content
Open
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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ With the generic resources:
| [azure_mysql_server](https://docs.chef.io/inspec/resources/azure_mysql_server/) | [azure_mysql_servers](https://docs.chef.io/inspec/resources/azure_mysql_servers/) |
| [azure_mysql_server_configuration](https://docs.chef.io/inspec/resources/azure_mysql_server_configuration/) | [azure_mysql_server_configurations](https://docs.chef.io/inspec/resources/azure_mysql_server_configurations/) |
| [azure_network_interface](https://docs.chef.io/inspec/resources/azure_network_interface/) | [azure_network_interfaces](https://docs.chef.io/inspec/resources/azure_network_interfaces/) |
| [azure_network_private_endpoint](https://docs.chef.io/inspec/resources/azure_network_private_endpoint/) | [azure_network_private_endpoints](https://docs.chef.io/inspec/resources/azure_network_private_endpoints/) |
| [azure_network_security_group](https://docs.chef.io/inspec/resources/azure_network_security_group/) | [azure_network_security_groups](https://docs.chef.io/inspec/resources/azure_network_security_groups/) |
| [azure_network_watcher](https://docs.chef.io/inspec/resources/azure_network_watcher/) | [azure_network_watchers](https://docs.chef.io/inspec/resources/azure_network_watchers/) |
| No Singular Resource | [azure_policy_assignments](https://docs.chef.io/inspec/resources/azure_policy_assignments/) |
Expand Down Expand Up @@ -437,6 +438,7 @@ They can be defined as environment variables or resource parameters (has priorit
| azurerm_mysql_database, azurerm_mysql_databases | `2017-12-01` | [azure_mysql_database](https://docs.chef.io/inspec/resources/azure_mysql_database/), [azure_mysql_databases](https://docs.chef.io/inspec/resources/azure_mysql_databases/) |
| azurerm_mysql_server, azurerm_mysql_servers | `2017-12-01` | [azure_mysql_server](https://docs.chef.io/inspec/resources/azure_mysql_server/), [azure_mysql_servers](https://docs.chef.io/inspec/resources/azure_mysql_servers/) |
| azurerm_network_interface, azurerm_network_interfaces | `2018-11-01` | [azure_network_interface](https://docs.chef.io/inspec/resources/azure_network_interface/), [azure_network_interfaces](https://docs.chef.io/inspec/resources/azure_network_interfaces/) |
| azurerm_network_private_endpoint, azurerm_network_private_endpoints | `2020-05-01` | [azure_network_private_endpoint](https://docs.chef.io/inspec/resources/azure_network_private_endpoint/), [azure_network_private_endpoints](https://docs.chef.io/inspec/resources/azure_network_private_endpoints/) |
| azurerm_network_security_group, azurerm_network_security_groups | `2018-02-01` | [azure_network_security_group](https://docs.chef.io/inspec/resources/azure_network_security_group/), [azure_network_security_groups](https://docs.chef.io/inspec/resources/azure_network_security_groups/) |
| azurerm_network_watcher, azurerm_network_watchers | `2018-02-01` | [azure_network_watcher](https://docs.chef.io/inspec/resources/azure_network_watcher/), [azure_network_watchers](https://docs.chef.io/inspec/resources/azure_network_watchers/) |
| azurerm_postgresql_database, azurerm_postgresql_databases | `2017-12-01` | [azure_postgresql_database](https://docs.chef.io/inspec/resources/azure_postgresql_database/), [azure_postgresql_databases](https://docs.chef.io/inspec/resources/azure_postgresql_databases/) |
Expand Down Expand Up @@ -645,8 +647,14 @@ rake tf:apply[api_management]
rake tf:apply[management_group]
```

- Private Endpoint

```shell
rake tf:apply[private_endpoint]
```

A combination of the above can be provided.

```shell
rake tf:apply[management_group,public_ip,network_watcher]
rake tf:apply[management_group,public_ip,network_watcher,private_endpoint]
```
72 changes: 72 additions & 0 deletions libraries/azure_network_private_endpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'azure_generic_resource'

class AzureNetworkPrivateEndpoint < AzureGenericResource
name 'azure_network_private_endpoint'
desc 'Verifies settings for an Azure Network Private Endpoint'
example <<-EXAMPLE
describe azure_network_private_endpoint(resource_group: "RESOURCE_GROUP", name: "private-endpoint-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.Network/privateEndpoints', opts)

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

def subnet_id
return unless exists?
properties&.subnet&.id
end

def network_interface_ids
return unless exists?
properties&.networkInterfaces&.map(&:id)
end

def private_link_service_connection_ids
return unless exists?
properties&.privateLinkServiceConnections
&.map { |conn| conn.properties&.privateLinkServiceId }
&.compact
end

def manual_private_link_service_connection_ids
return unless exists?
properties&.manualPrivateLinkServiceConnections
&.map { |conn| conn.properties&.privateLinkServiceId }
&.compact
end

def to_s
super(AzureNetworkPrivateEndpoint)
end
end

# Provide the same functionality under the old resource name.
# This is for backward compatibility.
class AzurermNetworkPrivateEndpoint < AzureNetworkPrivateEndpoint
name 'azurerm_network_private_endpoint'
desc 'Verifies settings for an Azure Network Private Endpoint'
example <<-EXAMPLE
describe azurerm_network_private_endpoint(resource_group: "RESOURCE_GROUP", name: "private-endpoint-name") do
it { should exist }
end
EXAMPLE

def initialize(opts = {})
Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureNetworkPrivateEndpoint.name)
# 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)

# For backward compatibility.
opts[:api_version] ||= '2020-05-01'

super
end
end
67 changes: 67 additions & 0 deletions libraries/azure_network_private_endpoints.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require 'azure_generic_resources'

class AzureNetworkPrivateEndpoints < AzureGenericResources
name 'azure_network_private_endpoints'
desc 'Verifies settings for a collection of Azure Network Private Endpoints'
example <<-EXAMPLE
describe azure_network_private_endpoints 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.Network/privateEndpoints', 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.
table_schema = [
{ column: :names, field: :name },
{ 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(AzureNetworkPrivateEndpoints)
end
end

# Provide the same functionality under the old resource name.
# This is for backward compatibility.
class AzurermNetworkPrivateEndpoints < AzureNetworkPrivateEndpoints
name 'azurerm_network_private_endpoints'
desc 'Verifies settings for a collection of Azure Network Private Endpoints'
example <<-EXAMPLE
describe azurerm_network_private_endpoints do
it { should exist }
end
EXAMPLE

def initialize(opts = {})
Inspec::Log.warn Helpers.resource_deprecation_message(@__resource_name__, AzureNetworkPrivateEndpoints.name)
# 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)

# For backward compatibility.
opts[:api_version] ||= '2020-05-01'

super
end
end
27 changes: 26 additions & 1 deletion terraform/azure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ resource "azurerm_network_security_group" "nsg_open" {

resource "azurerm_virtual_network" "vnet" {
name = "Inspec-VNet"
address_space = ["10.1.1.0/24"]
address_space = ["10.1.0.0/16"]
location = var.location
resource_group_name = azurerm_resource_group.rg.name
}
Expand All @@ -328,6 +328,31 @@ resource "azurerm_subnet_network_security_group_association" "subnet_nsg" {
subnet_id = azurerm_subnet.subnet.id
}

resource "azurerm_subnet" "private_endpoint" {
count = var.private_endpoint_count
name = "Inspec-Private-Endpoint-Subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = "10.1.2.0/24"

enforce_private_link_endpoint_network_policies = false
}

resource "azurerm_private_endpoint" "storage_blob" {
count = var.private_endpoint_count
name = "inspec-storage-private-endpoint"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.private_endpoint[0].id

private_service_connection {
name = "inspec-storage-blob-connection"
private_connection_resource_id = azurerm_storage_account.sa.id
is_manual_connection = false
subresource_names = ["blob"]
}
}

resource "azurerm_network_interface" "nic1" {
name = "Inspec-NIC-1"
location = var.location
Expand Down
16 changes: 14 additions & 2 deletions terraform/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ output "vnet_address_space" {
}

output "vnet_subnets" {
value = [
azurerm_subnet.subnet.name]
value = compact(list(
azurerm_subnet.subnet.name,
var.private_endpoint_count > 0 ? azurerm_subnet.private_endpoint[0].name : ""
))
}

output "vnet_dns_servers" {
Expand Down Expand Up @@ -360,6 +362,16 @@ output "api_management_name" {
value = var.api_management_count > 0 ? azurerm_api_management.apim01[0].name : ""
}

output "private_endpoint_name" {
description = "the name for the azurerm_private_endpoint resource"
value = var.private_endpoint_count > 0 ? azurerm_private_endpoint.storage_blob[0].name : ""
}

output "private_endpoint_id" {
description = "the id for the azurerm_private_endpoint resource"
value = var.private_endpoint_count > 0 ? azurerm_private_endpoint.storage_blob[0].id : ""
}

output "azure_streaming_job_function_name" {
description = "the name for the azure_streaming_service_job"
value = azurer_stream_analytics_function_javascript_udf.streaming_job_function.name
Expand Down
4 changes: 4 additions & 0 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ variable "management_group_count" {
default = 1
}

variable "private_endpoint_count" {
default = 1
}

variable "policy_definition_name" {
default = "inspec_compliance_audit"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
resource_group = input('resource_group', value: nil)
private_endpoint_name = input('private_endpoint_name', value: '')

control 'azure_network_private_endpoint' do
title 'Testing the singular resource of azure_network_private_endpoint.'
desc 'Testing the singular resource of azure_network_private_endpoint.'

only_if { !private_endpoint_name.empty? }

describe azure_network_private_endpoint(resource_group: resource_group, name: private_endpoint_name) do
it { should exist }
its('name') { should cmp private_endpoint_name }
its('type') { should eq 'Microsoft.Network/privateEndpoints' }
its('subnet_id') { should_not be_nil }
its('network_interface_ids') { should be_an(Array) }
its('network_interface_ids') { should_not be_empty }
its('private_link_service_connection_ids') { should be_an(Array) }
its('private_link_service_connection_ids') { should_not be_empty }
end

describe azure_network_private_endpoint(resource_group: resource_group, name: 'fake') do
it { should_not exist }
end

describe azure_network_private_endpoint(resource_group: 'does-not-exist', name: private_endpoint_name) do
it { should_not exist }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
resource_group = input('resource_group', value: nil)
private_endpoint_name = input('private_endpoint_name', value: '')

control 'azure_network_private_endpoints' do
title 'Testing the plural resource of azure_network_private_endpoints.'
desc 'Testing the plural resource of azure_network_private_endpoints.'

only_if { !private_endpoint_name.empty? }

describe azure_network_private_endpoints(resource_group: resource_group) do
it { should exist }
its('names') { should include(private_endpoint_name) }
its('types') { should include('Microsoft.Network/privateEndpoints') }
end

describe azure_network_private_endpoints(resource_group: 'fake-group') do
it { should_not exist }
its('names') { should_not include('fake') }
end

describe azure_network_private_endpoints(resource_group: resource_group).where(name: private_endpoint_name) do
it { should exist }
end
end
79 changes: 79 additions & 0 deletions test/unit/resources/azure_network_private_endpoint_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
require_relative 'helper'
require 'azure_network_private_endpoint'
require 'ostruct'

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

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

def test_resource_group
assert_raises(ArgumentError) { AzureNetworkPrivateEndpoint.new(name: 'my-name') }
end

def test_subnet_id
resource = build_resource(
OpenStruct.new(subnet: OpenStruct.new(id: 'subnet-id')),
)

assert_equal('subnet-id', resource.subnet_id)
end

def test_network_interface_ids
resource = build_resource(
OpenStruct.new(networkInterfaces: [OpenStruct.new(id: 'nic-1'), OpenStruct.new(id: 'nic-2')]),
)

assert_equal(%w{nic-1 nic-2}, resource.network_interface_ids)
end

def test_private_link_service_connection_ids
resource = build_resource(
OpenStruct.new(
privateLinkServiceConnections: [
OpenStruct.new(properties: OpenStruct.new(privateLinkServiceId: 'pls-1')),
OpenStruct.new(properties: OpenStruct.new(privateLinkServiceId: nil)),
OpenStruct.new(properties: OpenStruct.new(privateLinkServiceId: 'pls-2')),
],
),
)

assert_equal(%w{pls-1 pls-2}, resource.private_link_service_connection_ids)
end

def test_manual_private_link_service_connection_ids
resource = build_resource(
OpenStruct.new(
manualPrivateLinkServiceConnections: [
OpenStruct.new(properties: OpenStruct.new(privateLinkServiceId: 'manual-pls-1')),
OpenStruct.new(properties: OpenStruct.new(privateLinkServiceId: nil)),
],
),
)

assert_equal(%w{manual-pls-1}, resource.manual_private_link_service_connection_ids)
end

def test_accessor_methods_return_nil_when_resource_does_not_exist
resource = build_resource(nil, exists: false)

assert_nil(resource.subnet_id)
assert_nil(resource.network_interface_ids)
assert_nil(resource.private_link_service_connection_ids)
assert_nil(resource.manual_private_link_service_connection_ids)
end

private

def build_resource(properties, exists: true)
resource = AzureNetworkPrivateEndpoint.allocate
resource.define_singleton_method(:exists?) { exists }
resource.define_singleton_method(:properties) { properties }
resource
end
end
Loading
Loading