Skip to content

inspec/inspec-gcp

Repository files navigation

InSpec GCP (Google Cloud Platform) Resource Pack

  • Project State-: Maintained

For more information on project states and SLAs, see this documentation.

This InSpec resource pack uses the native Google Cloud Platform (GCP) support in InSpec and provides the required resources to write tests for GCP.

This implementation was inspired on the ideas by Martez Reed.

Prerequisites

Install and configure the Google cloud SDK*

Download the SDK and run the installation:

./google-cloud-sdk/install.sh

Create credentials file via:

gcloud auth application-default login

If successful, this should be similar to:

$ cat ~/.config/gcloud/application_default_credentials.json

{
  "client_id": "764086051850-6qr4p6gpi6hn50asdr.apps.googleusercontent.com",
  "client_secret": "d-fasdfasdfasdfaweroi23jknrmfs;f8sh",
  "refresh_token": "1/asdfjlklwna;ldkna'dfmk-lCkju3-yQmjr20xVZonrfkE48L",
  "type": "authorized_user"
}

While InSpec can use user accounts for authentication, Google Cloud documentation recommends using service accounts.

Create Service Accounts

  1. Go to Console in the Google Cloud.
  2. Click on Service Accounts.
  3. Click on Create Service Accounts and give the required details.
  4. Click on Done.
  5. Now Click on Keys Tab.
  6. Click on Add Key.
  7. Click on Create New Key.
  8. Select the Key type as JSON.
  9. Click on Create.
  10. The Service Account Key will be downloaded. For example: myproject-1-feb7993e8660.jsonmyproject-1-feb7993e8660.json
  11. Move the key to the ~/.config/gcloud folder. If the file gets downloaded in the Downloads folder, use the below command.
mv ~/Downloads/myproject-1-feb7993e8660.json ~/.config/gcloud/
  1. The json credential file for a service account looks like this:
$ cat ~/.config/gcloud/myproject-1-feb7993e8660.json
{
  "type": "service_account",
  "project_id": "myproject-1",
  "private_key_id": "eb45b2fc0c33ea9b6fa212aaa08b1ed814bf8660",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADAN3662...fke9n6LAf268E/4EWhIzg==\n-----END PRIVATE KEY-----\n",
  "client_email": "auto-testing@myproject-1.iam.gserviceaccount.com",
  "client_id": "112144174133171863632",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/auto-testing%40myproject-1.iam.gserviceaccount.com"
}
  1. Now Setup the environmental variable for the 'GOOGLE_APPLICATION_CREDENTIALS'. And InSpec can be instructed to use it by setting this ENV variable prior to running inspec exec:
$ export GOOGLE_APPLICATION_CREDENTIALS='~/.config/gcloud/myproject-1-feb7993e8660.json'

NOTE:

If still error comes, please check your IAM roles and permissions.

Enable the appropriate APIs that you want to use:

Use the resources

Since this is an InSpec resource pack, it only defines InSpec resources. It includes example tests only. To easily use the GCP resources in your tests do the following:

Create a new profile for GCP

$ inspec init profile --platform gcp my-gcp-profile

Create new profile at /Users/spaterson/my-gcp-profile
 * Create directory libraries
 * Create file README.md
 * Create directory controls
 * Create file controls/example.rb
 * Create file inspec.yml
 * Create file attributes.yml
 * Create file libraries/.gitkeep

Update inputs.yml to point to your project

gcp_project_id: 'my-gcp-project'

The generated inspec.yml file automatically points to the InSpec GCP resource pack:

name: my-gcp-profile
title: My GCP InSpec Profile
version: 0.1.0
inspec_version: '>= 4'
inputs:
  - name: gcp_project_id
    required: true
    description: 'The GCP project identifier.'
depends:
  - name: inspec-gcp
    url: https://github.com/inspec/inspec-gcp/archive/x.tar.gz
supports:
  - platform: gcp

(For available inspec-gcp versions, see this list of inspec-gcp versions.)

Run the tests

$ cd my-gcp-profile/
$ inspec exec . -t gcp:// --input-file inputs.yml

Profile: GCP InSpec Profile (my-profile)
Version: 0.1.0
Target:  gcp://local-service-account@my-gcp-project.iam.gserviceaccount.com
Target ID: 8123456-12a3-1234-123a-a12s5c5abcx1

  âś”  gcp-single-region-1.0: Ensure single region has the correct properties.
     âś”  Region europe-west2 zone_names should include "europe-west2-a"
  âś”  gcp-regions-loop-1.0: Ensure regions have the correct properties in bulk.
     âś”  Region asia-east1 is expected to be up
     âś”  Region asia-east2 is expected to be up
     âś”  Region asia-northeast1 is expected to be up
     âś”  Region asia-northeast2 is expected to be up
     âś”  Region asia-northeast3 is expected to be up
     âś”  Region asia-south1 is expected to be up
     âś”  Region asia-south2 is expected to be up
     âś”  Region asia-southeast1 is expected to be up
     âś”  Region asia-southeast2 is expected to be up
     âś”  Region australia-southeast1 is expected to be up
     âś”  Region australia-southeast2 is expected to be up
     âś”  Region europe-central2 is expected to be up
     âś”  Region europe-north1 is expected to be up
     âś”  Region europe-southwest1 is expected to be up
     âś”  Region europe-west1 is expected to be up
     âś”  Region europe-west2 is expected to be up
     âś”  Region europe-west3 is expected to be up
     âś”  Region europe-west4 is expected to be up
     âś”  Region europe-west6 is expected to be up
     âś”  Region europe-west8 is expected to be up
     âś”  Region europe-west9 is expected to be up
     âś”  Region me-west1 is expected to be up
     âś”  Region northamerica-northeast1 is expected to be up
     âś”  Region northamerica-northeast2 is expected to be up
     âś”  Region southamerica-east1 is expected to be up
     âś”  Region southamerica-west1 is expected to be up
     âś”  Region us-central1 is expected to be up
     âś”  Region us-east1 is expected to be up
     âś”  Region us-east4 is expected to be up
     âś”  Region us-east5 is expected to be up
     âś”  Region us-south1 is expected to be up
     âś”  Region us-west1 is expected to be up
     âś”  Region us-west2 is expected to be up
     âś”  Region us-west3 is expected to be up
     âś”  Region us-west4 is expected to be up


Profile:   Google Cloud Platform Resource Pack (inspec-gcp)
Version:   1.10.37
Target:    gcp://local-service-account@my-gcp-project.iam.gserviceaccount.com
Target ID: 8123456-12a3-1234-123a-a12s5c5abcx1

     No tests executed.

Profile Summary: 2 successful controls, 0 control failures, 0 controls skipped
Test Summary:  36 successful, 0 failures, 0 skipped

Resource documentation

The following resources are available in the InSpec GCP Profile

InSpec GCP Supported Resources https://www.inspec.io/docs/reference/resources/#gcp-resources
Singular Resource Plural Resource
google_access_context_manager_access_level google_access_context_manager_access_levels
google_access_context_manager_access_policy google_access_context_manager_access_policies
google_access_context_manager_service_perimeter google_access_context_manager_service_perimeters
google_apigeegoogle_apigee_organization_envgroup google_apigee_organization_envgroups
google_apigee_organization_envgroup_attachment google_apigee_organization_envgroup_attachments
google_appengine_standard_app_version google_appengine_standard_app_versions
google_bigquery_dataset google_bigquery_datasets
google_bigquery_table google_bigquery_tables
google_billing_project_billing_info No Plural Resource
google_cloud_scheduler_job google_cloud_scheduler_jobs
google_cloudbuild_trigger google_cloudbuild_triggers
google_cloudfunctions_cloud_function google_cloudfunctions_cloud_functions
google_composer_project_location_environment google_composer_project_location_environments
google_compute_address google_compute_addresses
google_compute_autoscaler google_compute_autoscalers
google_compute_backend_bucket No Plural Resource
google_compute_backend_service google_compute_backend_services
google_compute_disk google_compute_disks
google_compute_disk_type google_compute_disk_types
google_data_loss_prevention_inspect_template google_data_loss_prevention_inspect_templates
google_compute_external_vpn_gateway google_compute_external_vpn_gateways
google_compute_firewall google_compute_firewalls
google_compute_forwarding_rule google_compute_forwarding_rules
google_compute_global_address google_compute_global_addresses
google_compute_global_forwarding_rule google_compute_global_forwarding_rules
google_compute_global_network_endpoint_group google_compute_global_network_endpoint_groups
google_compute_global_operation google_compute_global_operations
google_compute_health_check google_compute_health_checks
google_compute_health_check_service google_compute_health_check_services
google_compute_http_health_check google_compute_http_health_checks
google_compute_https_health_check google_compute_https_health_checks
google_compute_image_family_view No Plural Resource
google_compute_image No Plural Resource
google_compute_instance google_compute_instances
google_compute_instance google_compute_instances
google_compute_instance_group google_compute_instance_groups
google_compute_instance_group_manager google_compute_instance_group_managers
google_compute_instance_template google_compute_instance_templates
google_compute_interconnect google_compute_interconnects
google_compute_interconnect_location google_compute_interconnect_locations
google_compute_license_code No Plural Resource
google_compute_license google_compute_licenses
google_compute_machine_image google_compute_machine_images
google_compute_machine_type google_compute_machine_types
google_compute_network_attachment google_compute_network_attachments
google_compute_network_edge_security_service No Plural Resource
google_compute_network google_compute_networks
google_compute_network_endpoint_group google_compute_network_endpoint_groups
google_compute_network_firewall_policy google_compute_network_firewall_policies
google_compute_node_group google_compute_node_groups
google_compute_node_template google_compute_node_templates
google_compute_node_type google_compute_node_types
google_compute_packet_mirroring google_compute_packet_mirrorings
google_compute_project_info No Plural Resource
google_compute_public_delegated_prefix google_compute_public_delegated_prefixes
google_compute_region google_compute_regions
google_compute_region_backend_service google_compute_region_backend_services
google_compute_region_commitment google_compute_region_commitments
google_compute_region_disk_type google_compute_region_disk_types
google_compute_region_health_check google_compute_region_health_checks
google_compute_region_instance_group google_compute_region_instance_groups
google_compute_region_instance_group_manager google_compute_region_instance_group_managers
google_compute_region_operation google_compute_region_operations
google_compute_region_operation google_compute_region_operations
google_compute_regional_disk google_compute_regional_disks
google_compute_resource_policy google_compute_resource_policies
google_compute_route google_compute_routes
google_compute_router google_compute_routers
google_compute_router_nat google_compute_router_nats
google_compute_security_policy google_compute_security_policies
google_compute_snapshot google_compute_snapshots
google_compute_ssl_certificate google_compute_ssl_certificates
google_compute_ssl_policy google_compute_ssl_policies
google_compute_service_attachment google_compute_service_attachments
google_compute_subnetwork google_compute_subnetworks
google_compute_target_grpc_proxy google_compute_target_grpc_proxies
google_compute_subnetwork_iam_binding No Plural Resource
google_compute_subnetwork_iam_policy No Plural Resource
google_compute_target_http_proxy google_compute_target_http_proxies
google_compute_target_https_proxy google_compute_target_https_proxies
google_compute_target_https_proxy google_compute_target_https_proxies
google_compute_target_pool google_compute_target_pools
google_compute_target_ssl_proxy google_compute_target_ssl_proxies
google_compute_target_tcp_proxy google_compute_target_tcp_proxies
google_compute_url_map google_compute_url_maps
google_compute_vpn_tunnel google_compute_vpn_tunnels
No Singular Resource google_compute_xpn_resources
google_compute_zone google_compute_zones
google_compute_zone_operation google_compute_zone_operations
google_compute_region_target_http_proxy google_compute_region_target_http_proxies
google_container_cluster google_container_clusters
google_container_node_pool google_container_node_pools
google_container_server_config No Plural Resource
google_dataflow_project_location_job google_dataflow_project_location_jobs
google_dataproc_cluster google_dataproc_clusters
google_dns_managed_zone google_dns_managed_zones
google_dns_resource_record_set google_dns_resource_record_sets
google_dlp_dt google_dlp_dts
google_dlp_inspect_template google_dlp_inspect_templates
google_dlp_job_trigger google_dlp_job_triggers
google_dlp_job google_dlp_jobs
google_dlp_stored_info_type google_dlp_stored_info_types
google_filestore_instance google_filestore_instances
google_iam_organization_custom_role google_iam_organization_custom_roles
google_kms_crypto_key google_kms_crypto_keys
google_kms_crypto_key_iam_binding google_kms_crypto_key_iam_bindings
google_kms_crypto_key_iam_policy No Plural Resource
google_kms_crypto_key_version google_kms_crypto_key_versions
google_kms_ekm_connection google_kms_ekm_connections
google_kms_key_ring google_kms_key_rings
google_kms_key_ring_iam_binding google_kms_key_ring_iam_bindings
google_kms_key_ring_iam_policy No Plural Resource
google_kms_key_ring_import_job google_kms_key_ring_import_jobs
google_kms_location google_kms_locations
google_logging_folder_exclusion google_logging_folder_exclusions
google_logging_folder_log_sink google_logging_folder_log_sinks
google_logging_organization_log_sink google_logging_organization_log_sinks
google_logging_project_exclusion google_logging_project_exclusions
google_logging_project_sink google_logging_project_sinks
google_memcache_instance google_memcache_instances
google_ml_engine_model google_ml_engine_models
google_organization google_organizations
google_organization_iam_binding No Plural Resource
google_organization_iam_policy No Plural Resource
google_organization_policy No Plural Resource
google_project google_projects
google_project_alert_policy google_project_alert_policies
google_project_alert_policy_condition No Plural Resource
google_project_iam_binding google_project_iam_bindings
google_project_iam_custom_role google_project_iam_custom_roles
google_project_iam_policy No Plural Resource
google_project_logging_audit_config No Plural Resource
google_project_metric google_project_metrics
google_project_service google_project_services
google_pubsub_subscription google_pubsub_subscriptions
google_pubsub_subscription_iam_binding No Plural Resource
google_pubsub_subscription_iam_policy No Plural Resource
google_pubsub_topic google_pubsub_topics
google_pubsub_topic_iam_binding No Plural Resource
google_pubsub_topic_iam_policy No Plural Resource
google_redis_instance google_redis_instances
google_resourcemanager_folder google_resourcemanager_folders
google_resourcemanager_folder_iam_binding No Plural Resource
google_resourcemanager_folder_iam_policy No Plural Resource
google_runtime_config_config google_runtime_config_configs
google_runtime_config_config_iam_binding No Plural Resource
google_runtime_config_config_iam_policy No Plural Resource
google_runtime_config_variable google_runtime_config_variables
google_secret_manager_secret google_secret_manager_secrets
google_service_account google_service_accounts
No Singular Resource google_service_networking_service_connections
google_service_account_key google_service_account_keys
google_sourcerepo_repository google_sourcerepo_repositories
google_spanner_database google_spanner_databases
google_spanner_instance google_spanner_instances
google_spanner_instance_iam_binding No Plural Resource
google_spanner_instance_iam_policy No Plural Resource
google_sql_connect No Plural Resource
google_sql_database google_sql_databases
google_sql_database_instance google_sql_database_instances
No Singular Resource google_sql_flags
google_sql_operation google_sql_operations
google_sql_ssl_cert google_sql_ssl_certs
google_sql_user google_sql_users
google_storage_bucket google_storage_buckets
google_storage_bucket_acl No Plural Resource
google_storage_bucket_iam_binding google_storage_bucket_iam_bindings
google_storage_bucket_iam_policy No Plural Resource
google_storage_bucket_object google_storage_bucket_objects
google_storage_default_object_acl No Plural Resource
google_storage_object_acl No Plural Resource
google_user google_users
google_vertex_ai_batch_prediction_job google_vertex_ai_batch_prediction_jobs
google_vertex_ai_custom_job google_vertex_ai_custom_jobs
google_vertex_ai_dataset google_vertex_ai_datasets
google_vertex_ai_datasets_annotation_spec No Plural Resource
No Singular Resource google_vertex_ai_datasets_data_items
No Singular Resource google_vertex_ai_datasets_saved_queries
google_vertex_ai_endpoint google_vertex_ai_endpoints
google_vertex_ai_featurestore google_vertex_ai_featurestores
google_vertex_ai_featurestores_entity_type google_vertex_ai_featurestores_entity_types
google_vertex_ai_featurestore_entity_type_feature google_vertex_ai_featurestore_entity_type_features
google_vertex_ai_hyperparameter_tuning_job google_vertex_ai_hyperparameter_tuning_jobs
google_vertex_ai_index_endpoint google_vertex_ai_index_endpoints
google_vertex_ai_index google_vertex_ai_indices
google_vertex_ai_metadata_store google_vertex_ai_metadata_stores
google_vertex_ai_metadata_stores_artifact google_vertex_ai_metadata_stores_artifacts
google_vertex_ai_metadata_stores_context google_vertex_ai_metadata_stores_contexts
google_vertex_ai_metadata_stores_execution google_vertex_ai_metadata_stores_executions
google_vertex_ai_metadata_stores_metadata_schema google_vertex_ai_metadata_stores_metadata_schemas
google_vertex_ai_model_deployment_monitoring_job google_vertex_ai_model_deployment_monitoring_jobs
google_vertex_ai_model google_vertex_ai_models
google_vertex_ai_models_evaluation google_vertex_ai_models_evaluations
google_vertex_ai_models_evaluation_slice google_vertex_ai_models_evaluation_slices
google_vertex_ai_nas_job google_vertex_ai_nas_jobs
google_vertex_ai_nas_jobs_nas_trial_detail google_vertex_ai_nas_jobs_nas_trial_details
google_vertex_ai_pipeline_job google_vertex_ai_pipeline_jobs
google_vertex_ai_schedule google_vertex_ai_schedules
google_vertex_ai_study google_vertex_ai_studies
google_vertex_ai_studies_trial google_vertex_ai_studies_trials
google_vertex_ai_tensorboard google_vertex_ai_tensorboards
google_vertex_ai_tensorboards_experiment google_vertex_ai_tensorboards_experiments
google_vertex_ai_tensorboard_experiment_run google_vertex_ai_tensorboard_experiment_runs
google_vertex_ai_tensorboard_experiment_run_time_series_resource google_vertex_ai_tensorboard_experiment_run_time_series_resources
google_vertex_ai_training_pipeline google_vertex_ai_training_pipelines

Examples

Check SSH is Disabled for INGRESS across all GCP Projects

We use several plural resources for this example that loops across all projects and firewall rules. Making use of a plural resource property, we filter firewall rules for direction 'INGRESS' :

title 'Loop over all GCP projects and look at firewalls in INGRESS direction'

control 'gcp-projects-firewalls-loop-1.0' do

  impact 1.0
  title 'Ensure INGRESS firewalls in all projects have the correct properties using google_compute_firewall for detail.'

  google_projects.project_names.each do |project_name|
    google_compute_firewalls(project: project_name).where(firewall_direction: 'INGRESS').firewall_names.each do |firewall_name|
      describe google_compute_firewall(project: project_name, name: firewall_name) do
        its('allowed_ssh?')  { should be false }
      end
    end
  end
end

This example assumes there are sufficient privileges to list all GCP projects.

Check that a particular label exists on all VMs across all projects and zones

This check ensures that VMs have label must_be_there for each project:

title 'Loop over all GCP projects and ensure all VMs have a particular label'

control 'gcp-projects-zones-vm-label-loop-1.0' do

  impact 1.0
  title 'Ensure all VMs have must_be_there label key set'

  google_projects.project_names.each do |project_name|
    google_compute_zones(project: project_name).zone_names.each do |zone_name|
      google_compute_instances(project: project_name, zone: zone_name).instance_names.each do |instance_name|
        describe google_compute_instance(project: project_name, zone: zone_name, name: instance_name) do
          its('labels_keys') { should include 'must_be_there' }
        end
      end
    end
  end
end

This example verifies there are sufficient privileges to list all regions.

next unless google_compute_regions(project: gcp_project_id).resource_failed?
google_compute_regions(project: gcp_project_id).region_names.each do |region_name|
  describe google_compute_region(project: gcp_project_id,  region: region_name) do
    it { should be_up }
  end
end

if google_compute_regions(project: gcp_project_id).resource_failed?
  puts google_compute_regions(project: gcp_project_id).resource_exception_message
  puts google_compute_regions(project: gcp_project_id,name: region_name).pretty_inspect
end

This example assumes there are sufficient privileges to list all GCP projects.

Test inspec-gcp resources

  1. Create a new GCP project
  2. Ensure this is currently set following: https://cloud.google.com/shell/docs/examples
$ gcloud config set project <project-name>
$ gcloud config list project
  1. Enable billing for your new project
  2. Enable various services necessary to run the tests:
$ gcloud services enable compute.googleapis.com \
    sourcerepo.googleapis.com \
    dns.googleapis.com \
    container.googleapis.com \
    cloudkms.googleapis.com \
    cloudbuild.googleapis.com
  1. Environment variables can be used to specify project details e.g.
export GCP_PROJECT_NAME=<project-name>
export GCP_PROJECT_NUMBER=<project-number>
export GCP_PROJECT_ID=<project-id>

Some resources require elevated privileges to create in GCP. These are disabled by default but can be activated via:

export GCP_ENABLE_PRIVILEGED_RESOURCES=1

This takes effect during the "plan" task as described in the next section. Affected terraform resources are included/excluded and associated inspec tests enabled/disabled accordingly.

The resource pack defaults to region europe-west2. If a different region is desired e.g. us-central1, the following variables should be set:

export GCP_LOCATION="us-central1"
export GCP_ZONE="us-central1-a"
export GCP_LB_REGION="us-central1"
export GCP_LB_ZONE="us-central1-a"
export GCP_LB_ZONE_MIG2="us-central1-b"
export GCP_LB_ZONE_MIG3="us-central1-c"
export GCP_KUBE_CLUSTER_ZONE="us-central1-a"
export GCP_KUBE_CLUSTER_ZONE_EXTRA1="us-central1-b"
export GCP_KUBE_CLUSTER_ZONE_EXTRA2="us-central1-c"
export GCP_CLOUD_FUNCTION_REGION="us-central1"

Other regions can be targeted by updating the above. For example, see https://cloud.google.com/compute/docs/regions-zones/ for suitable values.

  1. Ensure the In-use IP addresses quota is set to 20 or above for chosen region

  2. Run the integration tests via:

bundle install && bundle exec rake test:integration

Alternatively, finer grained rake tasks are also available. Executing these in order is the same as the above command:

  • Initialize local workspace (terraform init)
bundle exec rake test:init_workspace
  • Plan integration tests - ensures variables are set for Inspec and Terraform, runs "terraform plan"
bundle exec rake test:plan_integration_tests
  • Set up integration tests - actually creates the resources in GCP (terraform apply)
bundle exec rake test:setup_integration_tests
  • Run integration tests - runs the tests (inspec exec)
bundle exec rake test:run_integration_tests
  • Clean up integration tests - removes GCP resources (terraform destroy)
bundle exec rake test:cleanup_integration_tests

Further Reading

FAQ

Failure running "inspec exec" on my GCP profile

If an error such as the below occurs when running "inspec exec" on a newly created GCP profile:

libraries/google_compute_instance.rb:26:in `block in initialize': undefined method `gcp_compute_client' for #<Train::Transports::Local::Connection:0x00007fcasdf1a532d0> (NoMethodError)

Check that the GCP transport is being specified as below:

$ inspec exec . -t gcp://

This tells the underlying transport layer (train) to use GCP.

access not configured error

InSpec relies on the GCP API's to verify the settings. Therefore, it requires access to the API. If you try to access an API via an InSpec resource that is not enabled in your account, then you see an error like:

googleapi: Error 403: Access Not Configured. Compute Engine API has not been used in project 41111111111 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview then retry.

Quota increase

The terraform templates generate sufficient resources to require an increase to default in_use IP addresses. Normally new projects have 10, increasing this to 20 or higher should be sufficient.

To find this setting, log in to the GCP web interface and go to IAM and admin->Quotas and look for "Compute Engine API In-use IP addresses". From here you can "Edit quotas" to request more.

Changed Quota:
+----------------------+------------------+
| Region: europe-west2 | IN_USE_ADDRESSES |
+----------------------+------------------+
|       Changes        |     8 -> 64      |
+----------------------+------------------+

Errors on terraform destroy

Sometimes there can be occasional errors when performing the cleanup rake task. This happens when resources are already deleted and can be ignored.

Upgrading to version 1.0

A guide on upgrading to version 1.0 can be found here

Support

The InSpec GCP resources are community supported. For bugs and features, please open a github issue and label it appropriately.

Kudos

This implementation is inspired by inspec-azure and inspec-gcp