From 3afc5dbdd3f9fdc08047d19d0e3487df680d8ea1 Mon Sep 17 00:00:00 2001 From: Janos Laszlo Vasik Date: Tue, 14 Nov 2023 10:41:44 +0100 Subject: [PATCH] dev(REST): RHINENG-2752 add rules endpoint nested under profiles of security_guides --- spec/api/v2/schemas/rules.rb | 57 +++++ spec/integration/v2/security_guides_spec.rb | 228 ++++++++++++++++++++ 2 files changed, 285 insertions(+) create mode 100644 spec/api/v2/schemas/rules.rb diff --git a/spec/api/v2/schemas/rules.rb b/spec/api/v2/schemas/rules.rb new file mode 100644 index 0000000000..37677d390b --- /dev/null +++ b/spec/api/v2/schemas/rules.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require './spec/api/v2/schemas/util' + +module Api + module V2 + module Schemas + module Rules + extend Api::V2::Schemas::Util + + RULE = { + type: :object, + required: %w[ref_id title rationale severity precedence], + properties: { + ref_id: { + type: :string, + examples: ['xccdf_org.ssgproject.content_rule_file_groupowner_etc_passwd'], + description: 'Identificator for Rule' + }, + title: { + type: :string, + examples: ['Verify Group Who Owns passwd File'], + description: 'Brief description of the Rule content' + }, + description: { + type: :string, + examples: ['To properly set the group owner of /etc/passwd, run the command: ' \ + '$ sudo chgrp root /etc/passwd'], + description: 'Longer description of the Rule content' + }, + remediation_issue_id: { + type: :string, + examples: ['ssg:rhel7|rht-ccp|xccdf_org.ssgproject.content_rule_file_groupowner_etc_passwd'], + description: 'Identificator used to remediate issues tied to this rule' + }, + rationale: { + type: :string, + examples: ['The /etc/passwd file contains information about the users that are configured on the ' \ + 'system. Protection of this file is critical for system security.'], + description: 'Reasoning for this rule to exist' + }, + severity: { + type: :string, + examples: ['medium'], + description: 'Level of impact of this Rule' + }, + precedence: { + type: :number, + examples: ['828'], + description: 'Number of Rule\'s position in the application order' + } + } + }.freeze + end + end + end +end diff --git a/spec/integration/v2/security_guides_spec.rb b/spec/integration/v2/security_guides_spec.rb index 6886b5f418..6c43f58bc3 100644 --- a/spec/integration/v2/security_guides_spec.rb +++ b/spec/integration/v2/security_guides_spec.rb @@ -392,4 +392,232 @@ end end end + + let!(:rules) do + FactoryBot.create_list( + :v2_rule, + 3, + security_guide: security_guides.first, + profile_id: prof_id + ) + end + let(:rule_id) { rules.first.id } + + path '/security_guides/{sg_id}/profiles/{prof_id}/rules' do + get 'List all Rules under a Profile of a Security Guide' do + tags 'security_guide' + description 'Lists all Rules under a Profile of a Security Guide' + operationId 'ListRules' + content_types + parameter name: :sg_id, in: :path, type: :string + parameter name: :prof_id, in: :path, type: :string + pagination_params_v2 + sort_params_v2(V2::Rule) + search_params_v2(V2::Rule) + + response '200', 'Lists all Rules under a Profile of a Security Guide' do + schema type: :object, + properties: { + meta: ref_schema('metadata'), + links: ref_schema('links'), + data: { + type: :array, + items: { + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + } + + after { |e| autogenerate_examples(e, 'List of Rules under a Profile of a Security Guide') } + + run_test! + end + + response '200', 'Lists all Rules under a Profile of a Security Guide requested' do + let(:sort_by) { ['severity'] } + schema type: :object, + properties: { + meta: ref_schema('metadata'), + links: ref_schema('links'), + data: { + type: :array, + items: { + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + } + + after do |e| + autogenerate_examples(e, 'List of Rules under a Profile of a Security Guide sorted by "title:asc"') + end + + run_test! + end + + response '200', 'Lists all Rules under a Profile of a Security Guide requested' do + let(:filter) { '(severity=high)' } + schema type: :object, + properties: { + meta: ref_schema('metadata'), + links: ref_schema('links'), + data: { + type: :array, + items: { + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + } + + after do |e| + autogenerate_examples(e, 'List of Rules under a Profile of a Security Guide filtered by ' \ + '"(severity=high)"') + end + + run_test! + end + + response '422', 'Returns error if wrong parameters are used' do + let(:sort_by) { ['rationale'] } + schema type: :object, + properties: { + meta: ref_schema('metadata'), + links: ref_schema('links'), + data: { + type: :array, + items: { + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + } + + after { |e| autogenerate_examples(e, 'Description of an error when sorting by incorrect parameter') } + + run_test! + end + + response '422', 'Returns error if wrong parameters are used' do + let(:limit) { 103 } + schema type: :object, + properties: { + meta: ref_schema('metadata'), + links: ref_schema('links'), + data: { + type: :array, + items: { + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + } + + after { |e| autogenerate_examples(e, 'Description of an error when requesting higher limit than supported') } + + run_test! + end + + response '404', 'Rules not found' do + let(:sg_id) { Faker::Internet.uuid } + + after do |e| + autogenerate_examples(e, 'Description of an error when the requested Rules of a Profile are ' \ + 'under a different or nonexistent Security Guide') + end + + run_test! + end + + response '404', 'Rules not found' do + let(:prof_id) { Faker::Internet.uuid } + + after do |e| + autogenerate_examples(e, 'Description of an error when the requested Rules are ' \ + 'under a different or nonexistent Profile') + end + + run_test! + end + end + end + + path '/security_guides/{sg_id}/profiles/{prof_id}/rules/{rule_id}' do + get 'Returns a Rule under a Profile of a Security Guide' do + tags 'security_guide' + description 'Returns requested Rule under a Profile of a Security Guide' + operationId 'ShowRule' + content_types + parameter name: :sg_id, in: :path, type: :string + parameter name: :prof_id, in: :path, type: :string + parameter name: :rule_id, in: :path, type: :string + + response '200', 'Returns requested Rule' do + schema type: :object, + properties: { + data: { + type: :object, + properties: { + type: { type: :string }, + id: ref_schema('id'), + attributes: ref_schema('rules') + } + } + } + + after do |e| + binding.pry + autogenerate_examples(e, 'Requested Rule') + end + + run_test! + end + + response '404', 'Rule not found' do + let(:sg_id) { Faker::Internet.uuid } + + after do |e| + autogenerate_examples(e, 'Description of an error when the requested Rule is ' \ + 'under a different or nonexistent Security Guide') + end + + run_test! + end + + response '404', 'Rule not found' do + let(:prof_id) { Faker::Internet.uuid } + + after do |e| + autogenerate_examples(e, 'Description of an error when the requested Rule is ' \ + 'under a different or nonexistent Profile') + end + + run_test! + end + + response '404', 'Rule not found' do + let(:rule_id) { Faker::Internet.uuid } + + after { |e| autogenerate_examples(e, 'Description of an error when the requested Rule is not found') } + + run_test! + end + end + end end