diff --git a/qa/qa/ee/page/project/registry/show.rb b/qa/qa/ee/page/project/registry/show.rb new file mode 100644 index 0000000000000000000000000000000000000000..27c65117180449f012b620917f260eff26938acf --- /dev/null +++ b/qa/qa/ee/page/project/registry/show.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module QA + module EE + module Page + module Project + module Registry + module Show + extend QA::Page::PageConcern + + def self.prepended(base) + super + + base.class_eval do + view 'ee/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/' \ + 'list_page/container_scanning_counts.vue' do + element 'counts' + end + end + end + + def has_non_zero_counts? + within_element('counts') do + has_text?(%r{\b[1-9]\d*\s+critical\b}) || + has_text?(%r{\b[1-9]\d*\s+high\b}) || + has_text?(%r{\b[1-9]\d*\s+other\b}) + end + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/registry/show.rb b/qa/qa/page/project/registry/show.rb index 0deeb5b4ae08584ed0bd8ece9e7b2fe5c610e9f4..6b6187c1594b263d36dd1a67cc3b58e137227506 100644 --- a/qa/qa/page/project/registry/show.rb +++ b/qa/qa/page/project/registry/show.rb @@ -41,3 +41,5 @@ def click_delete end end end + +QA::Page::Project::Registry::Show.prepend_mod_with('Page::Project::Registry::Show', namespace: QA) diff --git a/qa/qa/page/project/secure/configuration_form.rb b/qa/qa/page/project/secure/configuration_form.rb index fd79cee71f0660e3e02140895bd85f56e40ebe2a..762b4566641503c92c8344000a0567a6075f5e1d 100644 --- a/qa/qa/page/project/secure/configuration_form.rb +++ b/qa/qa/page/project/secure/configuration_form.rb @@ -92,6 +92,14 @@ def enable_secret_detection end end + def enable_reg_scan + card = find_security_testing_card('Container Scanning For Registry') + within(card) do + # The GitLabUI toggle uses a Close Icon button + click_element('close-xs-icon') + end + end + private def go_to_tab(name) diff --git a/qa/qa/service/docker_run/container_registry_utils.rb b/qa/qa/service/docker_run/container_registry_utils.rb new file mode 100644 index 0000000000000000000000000000000000000000..ec466309cb25f4ebbc166dadfca931f8026ebe1e --- /dev/null +++ b/qa/qa/service/docker_run/container_registry_utils.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Service + module DockerRun + class ContainerRegistryUtils < Base + def tag_image(current_tag, new_tag) + run_docker_command("tag #{current_tag} #{new_tag}") + end + + def push_image(tag) + run_docker_command("push #{tag}") + end + + private + + def run_docker_command(command) + shell("docker #{command}") + end + end + end + end +end diff --git a/qa/qa/specs/features/ee/browser_ui/13_secure/cvs_container_registry_spec.rb b/qa/qa/specs/features/ee/browser_ui/13_secure/cvs_container_registry_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..92cc41390bc8a20007910e70155d306918636a8b --- /dev/null +++ b/qa/qa/specs/features/ee/browser_ui/13_secure/cvs_container_registry_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Secure', :secure_container_reg_cvs, :runner, + product_group: :composition_analysis, + only: { subdomain: %i[staging staging-canary] }, + feature_flag: { name: 'cvs_for_container_scanning', scope: :project } do + describe 'Continuous Vulnerability Scanning' do + let(:image_tag) { 'alpine:3.10.0' } + let(:registry_password_token) { ENV.fetch('GITLAB_QA_ACCESS_TOKEN') { raise 'GITLAB_QA_ACCESS_TOKEN required' } } + + let!(:project) do + create(:project, :with_readme, + name: 'container-registry-cvs-project', + description: 'Container Registry CVS Project') + end + + let(:registry_host) do + address = Runtime::Scenario.gitlab_address + uri = address.is_a?(URI) ? address : URI.parse(address) + "registry.#{uri.host}" + end + + let(:new_image_tag) { "#{registry_host}/#{project.full_path}:latest" } + let(:docker_utils) { QA::Service::DockerRun::ContainerRegistryUtils.new } + + before do + Runtime::Feature.enable(:cvs_for_container_scanning, project: project) + Flow::Login.sign_in + end + + context 'when a container is tagged with latest' do + it('performs a container scan', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/499672') do + configure_security_scanning + push_container_image + verify_scanning_job + navigate_to_vulnerability_details + EE::Page::Project::Secure::VulnerabilityDetails.perform do |vulnerability_details| + expect(vulnerability_details).to have_scanner('GitLab SBoM Vulnerability Scanner') + end + end + end + + private + + def configure_security_scanning + project.visit! + Page::Project::Menu.perform(&:go_to_security_configuration) + Page::Project::Secure::ConfigurationForm.perform(&:enable_reg_scan) + end + + def push_container_image + docker_utils.login(registry_host, + user: Runtime::Env.user_username, + password: registry_password_token) + docker_utils.tag_image(image_tag, new_image_tag) + docker_utils.push_image(new_image_tag) + end + + def verify_scanning_job + Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project) + project.visit_job('container_scanning') + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + end + + def navigate_to_vulnerability_details + Page::Project::Menu.perform(&:go_to_container_registry) + Page::Project::Registry::Show.perform do |registry| + expect(registry).to have_registry_repository(project.name) + expect(registry).to have_non_zero_counts + registry.click_link_with_text('View vulnerabilities') + end + EE::Page::Project::Secure::SecurityDashboard.perform do |vulnerability_report| + vulnerability_report.click_vulnerability( + description: 'apk-tools in alpine 3.10.0 is vulnerable to CVE-2021-30139') + end + end + end + end +end