- Project State: Maintained
For more information on project states and SLAs, see this documentation.
This InSpec resource pack uses the Azure REST API and provides the required resources to write tests for resources in Azure.
- InSpec for Azure
- Ruby
- Bundler installed
-The Azure CLI provides a command-line interface for interacting with Azure services. To enable authentication, you will need to install the Azure CLI.- https://learn.microsoft.com/en-us/cli/azure/install-azure-cli
az login --tenant AZURE_TENANT_ID
a. Use the az login --tenant AZURE_TENANT_ID
command to log in with a specific Azure tenant: If you have a specific Azure tenant ID, you can provide it as a parameter to the az login command. If you don't specify the tenant ID, the CLI will provide a list of available tenants.
b. If the CLI can open your default browser: If the CLI can open your default browser, it will initiate the authorization code flow and open the Azure sign-in page in the browser for authentication.
c. If no web browser is available or fails to open: In case a web browser is not available or fails to open, the CLI will initiate the device code flow. It will provide you with a code and instruct you to open a browser page at https://aka.ms/devicelogin. You need to enter the code displayed in your terminal on that page for authentication.
d. Storing retrieved credentials: The documentation suggests storing the retrieved credentials, such as tenant_id and subscription_id, in environment variables prefaced with AZURE_. It provides an example of using a .envrc file or creating environment variables using the preferred method.
AZURE_TENANT_ID=<your-azure-tenant-id-here>
AZURE_SUBSCRIPTION_ID=<your-azure-subscription-id-here>
Your Azure Service Principal Account must have a minimum of reader
role of the Azure roles to any subscription that you'd like to use this resource pack.
You must have the following pieces of information:
- TENANT_ID
- CLIENT_ID
- CLIENT_SECRET
- SUBSCRIPTION_ID
To create your account Service Principal Account:
- Log in to the Azure portal.
- Click Azure Active Directory.
- Click APP registrations.
- Click New application registration.
- Enter name and select Web from the Application Type drop-down.
- Save your application.
- Note your Application ID. This is your client_id.
- Click Certificates & secrets.
- Click New client secret.
- Create a new password. This value is your client_secret above.
- Go to your subscription (click All Services then subscriptions).
- Choose your subscription from that list.
- Note your Subscription ID.
- Click Access control (IAM).
- Click Add.
- Select the reader role.
- Select the application you created and click save.
These must be stored in an environment variables prefaced with AZURE_
. If you use Dotenv, then you can save these values in your own .envrc
file. Either source it or run direnv allow
. If you do not use Dotenv
, then you can create environment variables in the way that you prefer.
Since this is an InSpec resource pack, it only defines InSpec resources. To use these resources in your controls, you should create your profile:
inspec init profile --platform azure my-profile
Example inspec.yml
:
name: my-profile
title: My own Azure profile
version: 0.1.0
inspec_version: '>= 4.23.15'
depends:
- name: inspec-azure
url: https://github.com/inspec/inspec-azure/archive/x.tar.gz
supports:
- platform: azure
(For available inspec-azure versions, see this list of inspec-azure versions.)
- azure_generic_resource
- azure_generic_resources
- azure_graph_generic_resource
- azure_graph_generic_resources
With the generic resources:
- Azure cloud resources pack, which does not include a static InSpec resource and can be tested.
- Azure resources from different resource providers and resource groups can be tested at the same time.
- Server-side filtering can be used for more efficient tests.
Please refer to the specific resource pages for more details and different use cases.
Ensure that all resources have specified names within the subscription regardless of type and resource Group
azure_generic_resources(substring_of_name: 'NAME').ids.each do |id|
describe azure_generic_resource(resource_id: id) do
its('location') { should eq 'eastus' }
end
end
azure_generic_resources(tag_name: 'NAME').ids.each do |id|
describe azure_generic_resource(resource_id: id) do
its('location') { should eq 'eastus' }
end
end
describe azure_virtual_machine(resource_group: 'RESOURCE_GROUP', name: 'NAME-WEB-01') do
it { should exist }
it { should have_monitoring_agent_installed }
it { should_not have_endpoint_protection_installed([]) }
it { should have_only_approved_extensions(['MicrosoftMonitoringAgent']) }
its('type') { should eq 'Microsoft.Compute/virtualMachines' }
its('installed_extensions_types') { should include('MicrosoftMonitoringAgent') }
its('installed_extensions_names') { should include('LogAnalytics') }
end
describe azure_network_security_group(resource_group: 'RESOURCE_GROUP', name: 'NAME-SERVER') do
it { should exist }
its('type') { should eq 'Microsoft.Network/networkSecurityGroups' }
its('security_rules') { should_not be_empty }
its('default_security_rules') { should_not be_empty }
it { should_not allow_rdp_from_internet }
it { should_not allow_ssh_from_internet }
it { should allow(source_ip_range: '0.0.0.0', destination_port: '22', direction: 'inbound') }
it { should allow_in(service_tag: 'Internet', port: %w{1433-1434 1521 4300-4350 5000-6000}) }
end
The generic resources and their derivations support the following parameters unless stated otherwise on their specific resource page.
As an Azure resource provider enables new features, it releases a new version of the REST API. They are generally in the format of 2020-01-01
. InSpec Azure resources can be forced to use a specific version of the API to eliminate the behavioral changes between the tests using different API versions. The latest version is used unless a specific version is provided.
describe azure_virtual_machine(resource_group: 'RESOURCE_GROUP', name: 'NAME', api_version: '2020-01-01') do
its('api_version_used_for_query_state') { should eq 'user_provided' }
its('api_version_used_for_query') { should eq '2020-01-01' }
end
DEFAULT
api version can be used, if it is supported by the resource provider.
describe azure_generic_resource(resource_provider: 'Microsoft.Compute/virtualMachines', name: 'NAME', api_version: 'DEFAULT') do
its('api_version_used_for_query_state') { should eq 'DEFAULT' }
end
LATEST
version is determined by this resource pack within the supported API versions. If the latest version is a preview
, than an older, but a stable version might be used. Explicitly forcing to use the LATEST
version.
describe azure_virtual_networks(api_version: 'LATEST') do
its('api_version_used_for_query_state') { should eq 'LATEST' }
end
LATEST
version is used unless provided (Implicit).
describe azure_network_security_groups(resource_group: 'RESOURCE_GROUP') do
its('api_version_used_for_query_state') { should eq 'LATEST' }
end
LATEST
version is used if the provided is invalid.
describe azure_network_security_groups(resource_group: 'RESOURCE_GROUP', api_version: 'invalid_api_version') do
its('api_version_used_for_query_state') { should eq 'LATEST' }
end
Microsoft Azure cloud services are available through a global and three national networks of the datacenter as described here. The preferred data center can be defined via endpoint
parameter. Azure Global Cloud is used if not provided.
azure_cloud
(default)azure_china_cloud
azure_us_government_L4
azure_us_government_L5
azure_german_cloud
describe azure_virtual_machines(endpoint: 'azure_german_cloud') do
it { should exist }
end
It can be defined as an environment variable or a resource parameter (has priority).
The pre-defined environment variables for each cloud deployment can be found here.
The behavior of the HTTP client can be defined with the following parameters:
azure_retry_limit
: Maximum number of retries (default -2
, Integer).azure_retry_backoff
: Pause in seconds between retries (default -0
, Integer).azure_retry_backoff_factor
: The amount to multiply each successive retries interval amount by (default -1
, Integer).
They can be defined as environment variables or resource parameters (has priority).
WARNING The following resources are using their
azure_
counterparts under the hood, and they will be deprecated in the InSpec Azure version 2. Their API versions are fixed (see below) for full backward compatibility. It is strongly advised to start using the resources withazure_
prefix for an up-to-date testing experience.
Legacy Resource Name | Fixed API version | Replaced by |
---|---|---|
azurerm_ad_user, azurerm_ad_users | v1.0 |
azure_graph_user, azure_graph_users |
azurerm_aks_cluster, azurerm_aks_clusters | 2018-03-31 |
azure_aks_cluster, azure_aks_cluster |
azurerm_api_management, azurerm_api_managements | 2019-12-01 |
azure_api_management, azure_api_managements |
azurerm_application_gateway, azurerm_application_gateways | 2019-12-01 |
azure_application_gateway, azure_application_gateways |
azurerm_cosmosdb_database_account | 2015-04-08 |
azure_cosmosdb_database_account |
azurerm_event_hub_authorization_rule | 2017-04-01 |
azure_event_hub_authorization_rule |
azurerm_event_hub_event_hub | 2017-04-01 |
azure_event_hub_event_hub |
azurerm_event_hub_namespace | 2017-04-01 |
azure_event_hub_namespace |
azurerm_hdinsight_cluster | 2015-03-01-preview |
azure_hdinsight_cluster |
azurerm_iothub | 2018-04-01 |
azure_iothub |
azurerm_iothub_event_hub_consumer_group, azurerm_iothub_event_hub_consumer_groups | 2018-04-01 |
azure_iothub_event_hub_consumer_group, azure_iothub_event_hub_consumer_groups |
azurerm_key_vault, azurerm_key_vaults | 2016-10-01 |
azure_key_vault, azure_key_vaults |
azurerm_key_vault_key, azurerm_key_vault_keys | 2016-10-01 |
azure_key_vault_key, azure_key_vault_keys |
azurerm_key_vault_secret, azurerm_key_vault_secrets | 2016-10-01 |
azure_key_vault_secret, azure_key_vault_secrets |
azurerm_load_balancer, azurerm_load_balancers | 2018-11-01 |
azure_load_balancer, azure_load_balancers |
azurerm_locks | 2016-09-01 |
azure_locks |
azurerm_management_group, azurerm_management_groups | 2018-03-01-preview |
azure_management_group, azure_management_groups |
azurerm_mariadb_server, azurerm_mariadb_servers | 2018-06-01-preview |
azure_mariadb_server, azure_mariadb_servers |
azurerm_monitor_activity_log_alert, azurerm_monitor_activity_log_alerts | 2017-04-01 |
azure_monitor_activity_log_alert, azure_monitor_activity_log_alerts |
azurerm_monitor_log_profile, azurerm_monitor_log_profiles | 2016-03-01 |
azure_monitor_log_profile, azure_monitor_log_profiles |
azurerm_mysql_database, azurerm_mysql_databases | 2017-12-01 |
azure_mysql_database, azure_mysql_databases |
azurerm_mysql_server, azurerm_mysql_servers | 2017-12-01 |
azure_mysql_server, azure_mysql_servers |
azurerm_network_interface, azurerm_network_interfaces | 2018-11-01 |
azure_network_interface, azure_network_interfaces |
azurerm_network_security_group, azurerm_network_security_groups | 2018-02-01 |
azure_network_security_group, azure_network_security_groups |
azurerm_network_watcher, azurerm_network_watchers | 2018-02-01 |
azure_network_watcher, azure_network_watchers |
azurerm_postgresql_database, azurerm_postgresql_databases | 2017-12-01 |
azure_postgresql_database, azure_postgresql_databases |
azurerm_postgresql_server, azurerm_postgresql_servers | 2017-12-01 |
azure_postgresql_server, azure_postgresql_servers |
azurerm_public_ip | 2020-05-01 |
azure_public_ip |
azurerm_resource_groups | 2018-02-01 |
azure_resource_groups |
azurerm_role_definition, azurerm_role_definitions | 2015-07-01 |
azure_role_definition, azure_role_definitions |
azurerm_security_center_policy, azurerm_security_center_policies | 2015-06-01-Preview |
azure_security_center_policy, azure_security_center_policies |
azurerm_sql_database, azurerm_sql_databases | 2017-10-01-preview |
azure_sql_database, azure_sql_databases |
azurerm_sql_server, azurerm_sql_servers | 2018-06-01-preview |
azure_sql_server, azure_sql_servers |
azurerm_storage_account, azurerm_storage_accounts | 2017-06-01 |
azure_storage_account, azure_storage_accounts |
azurerm_storage_account_blob_container, azurerm_storage_account_blob_containers | 2018-07-01 |
azure_storage_account_blob_container, azure_storage_account_blob_containers |
azurerm_subnet, azurerm_subnets | 2018-02-01 |
azure_subnet, azure_subnets |
azurerm_subscription | 2019-10-01 |
azure_subscription |
azurerm_virtual_machine, azurerm_virtual_machines | 2017-12-01 |
azure_virtual_machine, azure_virtual_machines |
azurerm_virtual_machine_disk, azurerm_virtual_machine_disks | 2017-03-30 |
azure_virtual_machine_disk, azure_virtual_machine_disks |
azurerm_virtual_network, azurerm_virtual_networks | 2018-02-01 |
azure_virtual_network, azure_virtual_networks |
azurerm_webapp, azurerm_webapps | 2016-08-01 |
azure_webapp, azure_webapps |
If you would like to contribute to this project, please see Contributing Rules.
For a detailed walk-through of resource creation, see the Resource Creation Guide.
The static resource is an InSpec Azure resource that is used to interrogate a specific Azure resource, such as, azure_virtual_machine
, azure_key_vaults
. As opposed to the generic resources, they might have some static properties created by processing the dynamic properties of a resource, such as azure_virtual_machine.admin_username
.
The easiest way to start by checking the existing static resources. They have detailed information on leveraging the backend class within their comments.
The common parameters are:
resource_provider
: Such asMicrosoft.Compute/virtualMachines
. It has to be hardcoded in the code by the resource author via thespecific_resource_constraint
method, and it should be the first parameter defined in the resource. This method includes user-supplied input validation.display_name
: A generic one will be created unless defined.required_parameters
: Define mandatory parameters. Theresource_group
and resourcename
in the singular resources are default mandatory in the base class.allowed_parameters
: Define optional parameters. Theresource_group
is optional in plural resources, but this can be made mandatory in the static resource.resource_uri
: Azure REST API URI of a resource. This parameter should be used when a resource does not reside in a resource group. It requiresadd_subscription_id
to be set to eithertrue
orfalse
. See azure_policy_definition and azure_policy_definitions.add_subscription_id
: It indicates whether the subscription ID should be included in theresource_uri
or not.
The singular resource is used to test a specific resource of a specific type and should include all of the properties available, such as azure_virtual_machine
.
- In most cases,
resource_group
and resourcename
should be required from the users, and a single API call would be enough for creating methods on the resource. See azure_virtual_machine 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. - If a resource exists in another resource, such as a subnet on a virtual network, see azure_subnet.
- 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.
A plural resource is used to test the collection of resources of a specific type, such as, azure_virtual_machines
. This allows for tests to be written based on the group of resources.
- A standard plural resource does not require a parameter, except optional
resource_group
. See azure_mysql_servers. - All plural resources use FilterTable to be able to provide filtering within returned resources. The filter criteria must be defined
table_schema
Hash variable. - If the properties of the resource are to be manipulated before populating the FilterTable, a
populate_table
method has to be defined. See azure_virtual_machines. - If the resources exist in another resource, such as subnets of a virtual network, a
resource_path
has to be created. For that, the identifiers of the parent resource,resource_group
and virtual network namevnet
, must be required from the users. See azure_subnets.
The following instructions helps you get your development environment setup to run integration tests.
Copy .envrc-example
to .envrc
and fill in the fields with the values from your account.
export AZURE_SUBSCRIPTION_ID=<subscription id>
export AZURE_CLIENT_ID=<client id>
export AZURE_TENANT_ID=<tenant id>
export AZURE_CLIENT_SECRET=<client secret>
For PowerShell, set the following environment variables.
$env:AZURE_SUBSCRIPTION_ID="<subscription id>"
$env:AZURE_CLIENT_ID="<client id>"
$env:AZURE_CLIENT_SECRET="<client secret>"
$env:AZURE_TENANT_ID="<tenant id>"
in order to run tests along with mock train URI
export RAKE_ENV=test
- Follow the instructions for your platform here
- macOS:
brew update && brew install azure-cli
- macOS:
- Login with the azure-cli
rake azure:login
- Verify azure-cli is logged in:
az account show
First, ensure your system has Terraform installed.
This environment may be used to run your profile against or to run integration tests on it. We are using Terraform workspaces to allow teams to have unique environments without affecting each other.
Direnv is used to initialize an environment variable WORKSPACE
to your username. We recommend using direnv
and allowing it to run in your environment. However, if you prefer to not use direnv
you may also source .envrc
.
Creating a new environment:
rake azure:login
rake tf:apply
Updating a running environment (For example, when you change the .tf file):
rake tf:apply
Checking if your state has diverged from your plan:
rake tf:plan
Destroying your environment:
rake tf:destroy
To run Rubocop and Syntax, check for Ruby and InSpec:
rake test:lint
To run unit tests:
rake test:unit
To run integration tests:
rake test:integration
Please note that Graph API resource requires specific privileges granted to your service principal.
Please refer to the Microsoft Documentation for information on how to grant these permissions to your application.
To run a control called azure_virtual_machine
only:
rake test:integration[azurerm_virtual_machine]
Note that in zsh
you need to escape the [
, ]
characters.
You may run selected multiple controls only:
rake test:integration[azure_aks_cluster,azure_virtual_machine]
To run lint and unit tests:
rake
The creation of the following resources can be skipped if there are any resource constraints.
- Network Watcher
rake tf:apply[network_watcher]
- HDinsight Interactive Query Cluster
rake tf:apply[hdinsight_cluster]
- Public IP
rake tf:apply[public_ip]
- API Management
rake tf:apply[api_management]
- Management Group
rake tf:apply[management_group]
A combination of the above can be provided.
rake tf:apply[management_group,public_ip,network_watcher]