# Copyright 2019 The inspec-gcp-cis-benchmark Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title 'Ensure That Compute Instances Have Confidential Computing Enabled (Automated)'

gcp_project_id = input('gcp_project_id')
cis_version = input('cis_version')
cis_url = input('cis_url')
supported_confidential_vm_types = input('supported_confidential_vm_types', value: /^(n2d|c2d|n3d)/, description: 'Regex for machine types supporting Confidential Computing. N2D, C2D (AMD SEV). N3D (AMD SEV-SNP). T2D (Intel TDX) might also be relevant if supported by InSpec resources.')
control_id = '4.11'
control_abbrev = 'vms'

control "cis-gcp-#{control_id}-#{control_abbrev}" do
  impact 'medium'

  title "[#{control_abbrev.upcase}] Ensure That Compute Instances Have Confidential Computing Enabled (Automated)"

  desc 'Google Cloud encrypts data at-rest and in-transit, but customer data must be decrypted for processing. Confidential Computing is a breakthrough technology that encrypts data in-use while it is being processed. Confidential Computing environments keep data encrypted in memory and elsewhere outside the central processing unit (CPU). Confidential VMs leverage hardware-based memory encryption technologies... Customer data will stay encrypted while it is used, indexed, queried, or trained on. Encryption keys are generated by and reside solely in dedicated hardware and are not exportable, enhancing isolation and security. Built-in hardware optimizations ensure Confidential Computing workloads experience minimal to no significant performance penalties.'
  desc 'rationale', "Confidential Computing enables customers' sensitive code and other data encrypted in memory during processing. Google does not have access to the encryption keys. Confidential VM can help alleviate concerns about risk related to either dependency on Google infrastructure or Google insiders' access to customer data in the clear."

  tag cis_scored: true
  tag cis_level: 2
  tag cis_gcp: control_id.to_s
  tag cis_version: cis_version.to_s
  tag project: gcp_project_id.to_s
  tag nist: %w[] # Add relevant NIST controls if any in future

  ref 'CIS Benchmark', url: cis_url.to_s
  ref 'GCP Docs', url: 'https://cloud.google.com/compute/confidential-vm/docs/creating-cvm-instance'
  ref 'GCP Docs', url: 'https://cloud.google.com/compute/confidential-vm/docs/about-cvm'
  ref 'GCP Docs', url: 'https://cloud.google.com/confidential-computing'
  ref 'Google Cloud Blog', url: 'https://cloud.google.com/blog/products/identity-security/introducing-google-cloud-confidential-computing-with-confidential-vms'
  ref 'Supported Configurations', url: 'https://cloud.google.com/confidential-computing/confidential-vm/docs/supported-configurations'
  ref 'Pricing', url: 'https://cloud.google.com/compute/confidential-vm/pricing'

  # control_id and control_abbrev are already defined above
  # supported_confidential_vm_types is defined as an input above

  instances_found = false
  google_compute_zones(project: gcp_project_id).zone_names.each do |zone_name|
    google_compute_instances(project: gcp_project_id, zone: zone_name)
      .where(status: 'RUNNING')
      .where { machine_type.match(supported_confidential_vm_types) } # Filter for machine types that *can* support it
      .instance_names.each do |instance_name|
      instances_found = true
      describe "[#{gcp_project_id}] Confidential VM: #{instance_name} in Zone: #{zone_name}" do
        subject { google_compute_instance(project: gcp_project_id, zone: zone_name, name: instance_name).confidential_instance_config }
        its('enable_confidential_compute') { should be true }
      end
    end
  end

  unless instances_found
    describe "[#{control_abbrev.upcase}] #{control_id} - No Running Instances of Supported Machine Types Found" do
      skip 'No running compute instances of machine types supporting Confidential Computing (e.g., N2D, C2D, N3D) were found in the project. This control is Not Applicable or requires manual verification for instances not matching the filter.'
    end
  end
end
