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>2020-09-19 04:45:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 04:45:44 +0300
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /app/validators
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'app/validators')
-rw-r--r--app/validators/feature_flag_strategies_validator.rb95
-rw-r--r--app/validators/feature_flag_user_xids_validator.rb31
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json95
3 files changed, 203 insertions, 18 deletions
diff --git a/app/validators/feature_flag_strategies_validator.rb b/app/validators/feature_flag_strategies_validator.rb
new file mode 100644
index 00000000000..e542d52c50a
--- /dev/null
+++ b/app/validators/feature_flag_strategies_validator.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+class FeatureFlagStrategiesValidator < ActiveModel::EachValidator
+ STRATEGY_DEFAULT = 'default'.freeze
+ STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'.freeze
+ STRATEGY_USERWITHID = 'userWithId'.freeze
+ # Order key names alphabetically
+ STRATEGIES = {
+ STRATEGY_DEFAULT => [].freeze,
+ STRATEGY_GRADUALROLLOUTUSERID => %w[groupId percentage].freeze,
+ STRATEGY_USERWITHID => ['userIds'].freeze
+ }.freeze
+ USERID_MAX_LENGTH = 256
+
+ def validate_each(record, attribute, value)
+ return unless value
+
+ if value.is_a?(Array) && value.all? { |s| s.is_a?(Hash) }
+ value.each do |strategy|
+ strategy_validations(record, attribute, strategy)
+ end
+ else
+ error(record, attribute, 'must be an array of strategy hashes')
+ end
+ end
+
+ private
+
+ def strategy_validations(record, attribute, strategy)
+ validate_name(record, attribute, strategy) &&
+ validate_parameters_type(record, attribute, strategy) &&
+ validate_parameters_keys(record, attribute, strategy) &&
+ validate_parameters_values(record, attribute, strategy)
+ end
+
+ def validate_name(record, attribute, strategy)
+ STRATEGIES.key?(strategy['name']) || error(record, attribute, 'strategy name is invalid')
+ end
+
+ def validate_parameters_type(record, attribute, strategy)
+ strategy['parameters'].is_a?(Hash) || error(record, attribute, 'parameters are invalid')
+ end
+
+ def validate_parameters_keys(record, attribute, strategy)
+ name, parameters = strategy.values_at('name', 'parameters')
+ actual_keys = parameters.keys.sort
+ expected_keys = STRATEGIES[name]
+ expected_keys == actual_keys || error(record, attribute, 'parameters are invalid')
+ end
+
+ def validate_parameters_values(record, attribute, strategy)
+ case strategy['name']
+ when STRATEGY_GRADUALROLLOUTUSERID
+ gradual_rollout_user_id_parameters_validation(record, attribute, strategy)
+ when STRATEGY_USERWITHID
+ user_with_id_parameters_validation(record, attribute, strategy)
+ end
+ end
+
+ def gradual_rollout_user_id_parameters_validation(record, attribute, strategy)
+ percentage = strategy.dig('parameters', 'percentage')
+ group_id = strategy.dig('parameters', 'groupId')
+
+ unless percentage.is_a?(String) && percentage.match(/\A[1-9]?[0-9]\z|\A100\z/)
+ error(record, attribute, 'percentage must be a string between 0 and 100 inclusive')
+ end
+
+ unless group_id.is_a?(String) && group_id.match(/\A[a-z]{1,32}\z/)
+ error(record, attribute, 'groupId parameter is invalid')
+ end
+ end
+
+ def user_with_id_parameters_validation(record, attribute, strategy)
+ user_ids = strategy.dig('parameters', 'userIds')
+ unless user_ids.is_a?(String) && !user_ids.match(/[\n\r\t]|,,/) && valid_ids?(user_ids.split(","))
+ error(record, attribute, "userIds must be a string of unique comma separated values each #{USERID_MAX_LENGTH} characters or less")
+ end
+ end
+
+ def valid_ids?(user_ids)
+ user_ids.uniq.length == user_ids.length &&
+ user_ids.all? { |id| valid_id?(id) }
+ end
+
+ def valid_id?(user_id)
+ user_id.present? &&
+ user_id.strip == user_id &&
+ user_id.length <= USERID_MAX_LENGTH
+ end
+
+ def error(record, attribute, msg)
+ record.errors.add(attribute, msg)
+ false
+ end
+end
diff --git a/app/validators/feature_flag_user_xids_validator.rb b/app/validators/feature_flag_user_xids_validator.rb
new file mode 100644
index 00000000000..a840993a94b
--- /dev/null
+++ b/app/validators/feature_flag_user_xids_validator.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class FeatureFlagUserXidsValidator < ActiveModel::EachValidator
+ USERXID_MAX_LENGTH = 256
+
+ def validate_each(record, attribute, value)
+ self.class.validate_user_xids(record, attribute, value, attribute)
+ end
+
+ class << self
+ def validate_user_xids(record, attribute, user_xids, error_message_attribute_name)
+ unless user_xids.is_a?(String) && !user_xids.match(/[\n\r\t]|,,/) && valid_xids?(user_xids.split(","))
+ record.errors.add(attribute,
+ "#{error_message_attribute_name} must be a string of unique comma separated values each #{USERXID_MAX_LENGTH} characters or less")
+ end
+ end
+
+ private
+
+ def valid_xids?(user_xids)
+ user_xids.uniq.length == user_xids.length &&
+ user_xids.all? { |xid| valid_xid?(xid) }
+ end
+
+ def valid_xid?(user_xid)
+ user_xid.present? &&
+ user_xid.strip == user_xid &&
+ user_xid.length <= USERXID_MAX_LENGTH
+ end
+ end
+end
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index 995f2ad6616..8fde92d6312 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -52,67 +52,126 @@
{
"name": "brakeman",
"label": "Brakeman",
- "enabled" : true
+ "enabled" : true,
+ "description": "Ruby on Rails",
+ "variables": [
+ {
+ "field" : "SAST_BRAKEMAN_LEVEL",
+ "label" : "Brakeman confidence level.",
+ "type": "string",
+ "default_value": "1",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low, 2=Medium, 3=High."
+ }
+ ]
},
{
"name": "bandit",
"label": "Bandit",
- "enabled" : true
+ "enabled" : true,
+ "description": "Python",
+ "variables": [
+ {
+ "field" : "SAST_BANDIT_EXCLUDED_PATHS",
+ "label" : "Paths to exclude from scan.",
+ "type": "string",
+ "default_value": "",
+ "value": "",
+ "size": "SMALL",
+ "description": "Comma-separated list of paths to exclude from scan. Uses Python’s 'fnmatch' syntax; For example: '*/tests/*, */venv/*'"
+ }
+ ]
},
{
"name": "eslint",
"label": "ESLint",
- "enabled" : true
+ "enabled" : true,
+ "description": "JavaScript, TypeScript, React",
+ "variables": []
},
{
"name": "flawfinder",
"label": "Flawfinder",
- "enabled" : true
+ "enabled" : true,
+ "description": "C, C++",
+ "variables": [
+ {
+ "field" : "SAST_FLAWFINDER_LEVEL",
+ "label" : "Flawfinder risk level",
+ "type": "string",
+ "default_value": "1",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Flawfinder vulnerabilities under given risk level. Integer, 0=No risk, 5=High risk."
+ }
+ ]
},
{
"name": "kubesec",
"label": "kubesec",
- "enabled" : true
+ "enabled" : true,
+ "description": "Kubernetes manifests, Helm Charts",
+ "variables": []
},
{
- "name": "nodejsscan",
+ "name": "nodejs-scan",
"label": "Node.js Scan",
- "enabled" : true
+ "enabled" : true,
+ "description": "Node.js",
+ "variables": []
},
{
"name": "gosec",
"label": "Golang Security Checker",
- "enabled" : true
+ "enabled" : true,
+ "description": "Go",
+ "variables": [
+ {
+ "field" : "SAST_GOSEC_LEVEL",
+ "label" : "Gosec confidence level",
+ "type": "string",
+ "default_value": "0",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Gosec vulnerabilities under given confidence level. Integer, 0=Undefined, 1=Low, 2=Medium, 3=High."
+ }
+ ]
},
{
"name": "phpcs-security-audit",
"label": "PHP Security Audit",
- "enabled" : true
+ "enabled" : true,
+ "description": "PHP",
+ "variables": []
},
{
"name": "pmd-apex",
"label": "PMD APEX",
- "enabled" : true
+ "enabled" : true,
+ "description": "Apex (Salesforce)",
+ "variables": []
},
{
"name": "security-code-scan",
"label": "Security Code Scan",
- "enabled" : true
+ "enabled" : true,
+ "description": ".NET Core, .NET Framework",
+ "variables": []
},
{
"name": "sobelow",
"label": "Sobelow",
- "enabled" : true
+ "enabled" : true,
+ "description": "Elixir (Phoenix)",
+ "variables": []
},
{
"name": "spotbugs",
"label": "Spotbugs",
- "enabled" : true
- },
- {
- "name": "secrets",
- "label": "Secrets",
- "enabled" : true
+ "enabled" : true,
+ "description": "Groovy, Java, Scala",
+ "variables": []
}
]
}