Class: Inspec::WaiverFileReader

Inherits:
Object
  • Object
show all
Defined in:
lib/inspec/waiver_file_reader.rb

Constant Summary collapse

SUPPORTED_FILE_EXTENSION =
%w{.yaml .yml .csv .json}.freeze

Class Method Summary collapse

Class Method Details

.all_fieldsObject



67
68
69
# File 'lib/inspec/waiver_file_reader.rb', line 67

def self.all_fields
  %w{control_id justification expiration_date run}
end

.fetch_invalid_headers_info(headers, json_yaml = false) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/inspec/waiver_file_reader.rb', line 83

def self.fetch_invalid_headers_info(headers, json_yaml = false)
  required_fields = json_yaml ? %w{justification} : %w{control_id justification}
  data = {}
  data[:missing_required_fields] = []
  # Finds missing required fields
  unless (required_fields - headers).empty?
    data[:missing_required_fields] = required_fields - headers
  end
  # If column with no header found set the blank_column flag. Only applicable for csv
  data[:blank_column] = headers.include?(nil) ? true : false
  # Find extra headers/parameters
  data[:extra_headers] = (headers - all_fields)
  data
end

.fetch_waivers_by_profile(profile_id, files) ⇒ Object



10
11
12
13
# File 'lib/inspec/waiver_file_reader.rb', line 10

def self.fetch_waivers_by_profile(profile_id, files)
  read_waivers_from_file(profile_id, files) if @waivers_data.nil? || @waivers_data[profile_id].nil?
  @waivers_data[profile_id]
end

.parse_waiver_file(file_path) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/inspec/waiver_file_reader.rb', line 49

def self.parse_waiver_file(file_path)
  file_extension = File.extname(file_path).downcase

  case file_extension
  when ".yaml", ".yml"
    data = Secrets::YAML.resolve(file_path)&.inputs
    validate_json_yaml(data)
  when ".csv"
    data = Waivers::CSVFileReader.resolve(file_path)
    validate_csv_headers(Waivers::CSVFileReader.headers)
  when ".json"
    data = Waivers::JSONFileReader.resolve(file_path)
    validate_json_yaml(data)
  end

  data
end

.read_waivers_from_file(profile_id, files) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/inspec/waiver_file_reader.rb', line 15

def self.read_waivers_from_file(profile_id, files)
  @waivers_data ||= {}
  output = {}

  files.each do |file_path|
    next unless valid_waiver_file?(file_path)

    data = parse_waiver_file(file_path)
    output.merge!(data) if data.is_a?(Hash)
  rescue Inspec::Exceptions::WaiversFileNotReadable, Inspec::Exceptions::WaiversFileInvalidFormatting => e
    Inspec::Log.error "Error reading waivers file #{file_path}. #{e.message}"
    Inspec::UI.new.exit(:usage_error)
  end

  @waivers_data[profile_id] = output
end

.valid_waiver_file?(file_path) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/inspec/waiver_file_reader.rb', line 32

def self.valid_waiver_file?(file_path)
  # Check if the file is readable
  file_extension = File.extname(file_path).downcase
  unless SUPPORTED_FILE_EXTENSION.include?(file_extension)
    raise Inspec::Exceptions::WaiversFileNotReadable,
          "Unsupported file extension for '#{file_path}'. Allowed waiver file extensions: #{SUPPORTED_FILE_EXTENSION.join(", ")}"
  end

  # Check if the file is empty
  if File.zero?(file_path)
    Inspec::Log.warn "Waivers file '#{file_path}' is empty. Skipping waivers."
    return false
  end

  true
end

.validate_csv_headers(headers) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/inspec/waiver_file_reader.rb', line 71

def self.validate_csv_headers(headers)
  invalid_headers_info = fetch_invalid_headers_info(headers)
  # Warn if blank column found in csv file
  Inspec::Log.warn "Invalid column headers: Column can't be nil" if invalid_headers_info[:blank_column]
  # Warn if extra header found in csv file
  Inspec::Log.warn "Extra header/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
  unless invalid_headers_info[:missing_required_fields].empty?
    raise Inspec::Exceptions::WaiversFileInvalidFormatting,
    "Missing required header/s #{invalid_headers_info[:missing_required_fields]}. Fix headers in file to proceed."
  end
end

.validate_json_yaml(data) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/inspec/waiver_file_reader.rb', line 98

def self.validate_json_yaml(data)
  return if data.nil?

  missing_required_field = false
  data.each do |key, value|
    # In case of yaml or json we need to validate headers/parametes for each value
    invalid_headers_info = fetch_invalid_headers_info(value.keys, true)
    # WARN in case of extra parameters found in each waived control
    Inspec::Log.warn "Control ID #{key}: extra parameter/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
    unless invalid_headers_info[:missing_required_fields].empty?
      missing_required_field = true
      # Log error for each waived control
      Inspec::Log.error "Control ID #{key}: missing required parameter/s #{invalid_headers_info[:missing_required_fields]}"
    end
  end

  # Raise error if any of the waived control has missing required filed
  if missing_required_field
    raise Inspec::Exceptions::WaiversFileInvalidFormatting,
         "Missing required parameter [justification]. Fix parameters in file to proceed."
  end
end