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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /lib/security
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'lib/security')
-rw-r--r--lib/security/ci_configuration/sast_build_actions.rb170
1 files changed, 170 insertions, 0 deletions
diff --git a/lib/security/ci_configuration/sast_build_actions.rb b/lib/security/ci_configuration/sast_build_actions.rb
new file mode 100644
index 00000000000..b2d684bc1e1
--- /dev/null
+++ b/lib/security/ci_configuration/sast_build_actions.rb
@@ -0,0 +1,170 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class SastBuildActions
+ SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, sobelow, spotbugs'
+
+ def initialize(auto_devops_enabled, params, existing_gitlab_ci_content)
+ @auto_devops_enabled = auto_devops_enabled
+ @variables = variables(params)
+ @existing_gitlab_ci_content = existing_gitlab_ci_content || {}
+ @default_sast_values = default_sast_values(params)
+ @default_values_overwritten = false
+ end
+
+ def generate
+ action = @existing_gitlab_ci_content.present? ? 'update' : 'create'
+
+ update_existing_content!
+
+ [{ action: action, file_path: '.gitlab-ci.yml', content: prepare_existing_content, default_values_overwritten: @default_values_overwritten }]
+ end
+
+ private
+
+ def variables(params)
+ # This early return is necessary for supporting REST API.
+ # Will be removed during the implementation of
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/246737
+ return params unless params['global'].present?
+
+ 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'] = set_includes
+
+ @existing_gitlab_ci_content.select! { |k, v| v.present? }
+ @existing_gitlab_ci_content['sast'].select! { |k, v| v.present? }
+ end
+
+ def set_includes
+ includes = @existing_gitlab_ci_content['include'] || []
+ includes = includes.is_a?(Array) ? includes : [includes]
+ includes << { 'template' => template }
+ includes.uniq
+ 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 prepare_existing_content
+ content = @existing_gitlab_ci_content.to_yaml
+ content = remove_document_delimeter(content)
+
+ content.prepend(sast_comment)
+ end
+
+ def remove_document_delimeter(content)
+ content.gsub(/^---\n/, '')
+ end
+
+ def sast_comment
+ <<~YAML
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ YAML
+ 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