Welcome to mirror list, hosted at ThFree Co, Russian Federation.

sast_build_action.rb « ci_configuration « security « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 23dd4bd6d14dbfe0781a59cdabb4793aac72c367 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# frozen_string_literal: true

module Security
  module CiConfiguration
    class SastBuildAction < BaseBuildAction
      SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, semgrep, sobelow, spotbugs'

      def initialize(auto_devops_enabled, params, existing_gitlab_ci_content)
        super(auto_devops_enabled, existing_gitlab_ci_content)
        @variables = variables(params)
        @default_sast_values = default_sast_values(params)
        @default_values_overwritten = false
      end

      private

      def variables(params)
        collect_values(params, 'value')
      end

      def default_sast_values(params)
        collect_values(params, 'defaultValue')
      end

      def collect_values(config, key)
        global_variables = config['global']&.to_h { |k| [k['field'], k[key]] } || {}
        pipeline_variables = config['pipeline']&.to_h { |k| [k['field'], k[key]] } || {}

        analyzer_variables = collect_analyzer_values(config, key)

        global_variables.merge!(pipeline_variables).merge!(analyzer_variables)
      end

      def collect_analyzer_values(config, key)
        analyzer_variables = analyzer_variables_for(config, key)
        analyzer_variables['SAST_EXCLUDED_ANALYZERS'] = if key == 'value'
                                                          config['analyzers']
                                                          &.reject {|a| a['enabled'] }
                                                          &.collect {|a| a['name'] }
                                                          &.sort
                                                          &.join(', ')
                                                        else
                                                          ''
                                                        end

        analyzer_variables
      end

      def analyzer_variables_for(config, key)
        config['analyzers']
          &.select {|a| a['enabled'] && a['variables'] }
          &.flat_map {|a| a['variables'] }
          &.collect {|v| [v['field'], v[key]] }.to_h
      end

      def update_existing_content!
        @existing_gitlab_ci_content['stages'] = set_stages
        @existing_gitlab_ci_content['variables'] = set_variables(global_variables, @existing_gitlab_ci_content)
        @existing_gitlab_ci_content['sast'] = set_sast_block
        @existing_gitlab_ci_content['include'] = generate_includes

        @existing_gitlab_ci_content.select! { |k, v| v.present? }
        @existing_gitlab_ci_content['sast'].select! { |k, v| v.present? }
      end

      def set_stages
        existing_stages = @existing_gitlab_ci_content['stages'] || []
        base_stages = @auto_devops_enabled ? auto_devops_stages : ['test']
        (existing_stages + base_stages + [sast_stage]).uniq
      end

      def auto_devops_stages
        auto_devops_template = YAML.safe_load( Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content )
        auto_devops_template['stages']
      end

      def sast_stage
        @variables['stage'].presence ? @variables['stage'] : 'test'
      end

      def set_variables(variables, hash_to_update = {})
        hash_to_update['variables'] ||= {}

        variables.each do |key|
          if @variables[key].present? && @variables[key].to_s != @default_sast_values[key].to_s
            hash_to_update['variables'][key] = @variables[key]
            @default_values_overwritten = true
          else
            hash_to_update['variables'].delete(key)
          end
        end

        hash_to_update['variables']
      end

      def set_sast_block
        sast_content = @existing_gitlab_ci_content['sast'] || {}
        sast_content['variables'] = set_variables(sast_variables)
        sast_content['stage'] = sast_stage
        sast_content.select { |k, v| v.present? }
      end

      def template
        return 'Auto-DevOps.gitlab-ci.yml' if @auto_devops_enabled

        'Security/SAST.gitlab-ci.yml'
      end

      def global_variables
        %w(
          SECURE_ANALYZERS_PREFIX
        )
      end

      def sast_variables
        %w(
          SAST_ANALYZER_IMAGE_TAG
          SAST_EXCLUDED_PATHS
          SEARCH_MAX_DEPTH
          SAST_EXCLUDED_ANALYZERS
          SAST_BRAKEMAN_LEVEL
          SAST_BANDIT_EXCLUDED_PATHS
          SAST_FLAWFINDER_LEVEL
          SAST_GOSEC_LEVEL
        )
      end
    end
  end
end