Commit ad9ee37b authored by James Fargher's avatar James Fargher

Merge branch 'rf-sast-config-analyzer-info' into 'master'

Expose analyzer info for SAST Config

See merge request gitlab-org/gitlab!41825
parents 6698021a e3b580f5
...@@ -52,67 +52,126 @@ ...@@ -52,67 +52,126 @@
{ {
"name": "brakeman", "name": "brakeman",
"label": "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", "name": "bandit",
"label": "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", "name": "eslint",
"label": "ESLint", "label": "ESLint",
"enabled" : true "enabled" : true,
"description": "JavaScript, TypeScript, React",
"variables": []
}, },
{ {
"name": "flawfinder", "name": "flawfinder",
"label": "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", "name": "kubesec",
"label": "kubesec", "label": "kubesec",
"enabled" : true "enabled" : true,
"description": "Kubernetes manifests, Helm Charts",
"variables": []
}, },
{ {
"name": "nodejsscan", "name": "nodejs-scan",
"label": "Node.js Scan", "label": "Node.js Scan",
"enabled" : true "enabled" : true,
"description": "Node.js",
"variables": []
}, },
{ {
"name": "gosec", "name": "gosec",
"label": "Golang Security Checker", "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", "name": "phpcs-security-audit",
"label": "PHP Security Audit", "label": "PHP Security Audit",
"enabled" : true "enabled" : true,
"description": "PHP",
"variables": []
}, },
{ {
"name": "pmd-apex", "name": "pmd-apex",
"label": "PMD APEX", "label": "PMD APEX",
"enabled" : true "enabled" : true,
"description": "Apex (Salesforce)",
"variables": []
}, },
{ {
"name": "security-code-scan", "name": "security-code-scan",
"label": "Security Code Scan", "label": "Security Code Scan",
"enabled" : true "enabled" : true,
"description": ".NET Core, .NET Framework",
"variables": []
}, },
{ {
"name": "sobelow", "name": "sobelow",
"label": "Sobelow", "label": "Sobelow",
"enabled" : true "enabled" : true,
"description": "Elixir (Phoenix)",
"variables": []
}, },
{ {
"name": "spotbugs", "name": "spotbugs",
"label": "Spotbugs", "label": "Spotbugs",
"enabled" : true "enabled" : true,
}, "description": "Groovy, Java, Scala",
{ "variables": []
"name": "secrets",
"label": "Secrets",
"enabled" : true
} }
] ]
} }
...@@ -15186,24 +15186,49 @@ Represents an analyzer entity in SAST CI configuration ...@@ -15186,24 +15186,49 @@ Represents an analyzer entity in SAST CI configuration
""" """
type SastCiConfigurationAnalyzersEntity { type SastCiConfigurationAnalyzersEntity {
""" """
Analyzer description that is displayed on the form. Analyzer description that is displayed on the form
""" """
description: String description: String
""" """
Indicates whether an analyzer is enabled. Indicates whether an analyzer is enabled
""" """
enabled: Boolean enabled: Boolean
""" """
Analyzer label used in the config UI. Analyzer label used in the config UI
""" """
label: String label: String
""" """
Name of the analyzer. Name of the analyzer
""" """
name: String name: String
"""
List of supported variables
"""
variables(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): SastCiConfigurationEntityConnection
} }
""" """
......
...@@ -44190,6 +44190,59 @@ ...@@ -44190,6 +44190,59 @@
}, },
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
},
{
"name": "variables",
"description": "List of supported variables",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntityConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
} }
], ],
"inputFields": null, "inputFields": null,
...@@ -44206,7 +44259,7 @@ ...@@ -44206,7 +44259,7 @@
"fields": [ "fields": [
{ {
"name": "description", "name": "description",
"description": "Analyzer description that is displayed on the form.", "description": "Analyzer description that is displayed on the form",
"args": [ "args": [
], ],
...@@ -44220,7 +44273,7 @@ ...@@ -44220,7 +44273,7 @@
}, },
{ {
"name": "enabled", "name": "enabled",
"description": "Indicates whether an analyzer is enabled.", "description": "Indicates whether an analyzer is enabled",
"args": [ "args": [
], ],
...@@ -44234,7 +44287,7 @@ ...@@ -44234,7 +44287,7 @@
}, },
{ {
"name": "label", "name": "label",
"description": "Analyzer label used in the config UI.", "description": "Analyzer label used in the config UI",
"args": [ "args": [
], ],
...@@ -44248,7 +44301,7 @@ ...@@ -44248,7 +44301,7 @@
}, },
{ {
"name": "name", "name": "name",
"description": "Name of the analyzer.", "description": "Name of the analyzer",
"args": [ "args": [
], ],
...@@ -2107,10 +2107,10 @@ Represents an analyzer entity in SAST CI configuration. ...@@ -2107,10 +2107,10 @@ Represents an analyzer entity in SAST CI configuration.
| Field | Type | Description | | Field | Type | Description |
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `description` | String | Analyzer description that is displayed on the form. | | `description` | String | Analyzer description that is displayed on the form |
| `enabled` | Boolean | Indicates whether an analyzer is enabled. | | `enabled` | Boolean | Indicates whether an analyzer is enabled |
| `label` | String | Analyzer label used in the config UI. | | `label` | String | Analyzer label used in the config UI |
| `name` | String | Name of the analyzer. | | `name` | String | Name of the analyzer |
### SastCiConfigurationEntity ### SastCiConfigurationEntity
......
...@@ -9,16 +9,19 @@ module Types ...@@ -9,16 +9,19 @@ module Types
description 'Represents an analyzer entity in SAST CI configuration' description 'Represents an analyzer entity in SAST CI configuration'
field :name, GraphQL::STRING_TYPE, null: true, field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the analyzer.' description: 'Name of the analyzer'
field :label, GraphQL::STRING_TYPE, null: true, field :label, GraphQL::STRING_TYPE, null: true,
description: 'Analyzer label used in the config UI.' description: 'Analyzer label used in the config UI'
field :enabled, GraphQL::BOOLEAN_TYPE, null: true, field :enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates whether an analyzer is enabled.' description: 'Indicates whether an analyzer is enabled'
field :description, GraphQL::STRING_TYPE, null: true, field :description, GraphQL::STRING_TYPE, null: true,
description: 'Analyzer description that is displayed on the form.' description: 'Analyzer description that is displayed on the form'
field :variables, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
description: 'List of supported variables'
end end
end end
end end
......
...@@ -19,6 +19,10 @@ module Security ...@@ -19,6 +19,10 @@ module Security
fill_current_value_with_default_for(result, :pipeline) fill_current_value_with_default_for(result, :pipeline)
populate_current_value_for(result, :global) populate_current_value_for(result, :global)
populate_current_value_for(result, :pipeline) populate_current_value_for(result, :pipeline)
fill_current_value_with_default_for_analyzers(result)
populate_current_value_for_analyzers(result)
result result
end end
...@@ -46,10 +50,29 @@ module Security ...@@ -46,10 +50,29 @@ module Security
end end
end end
def fill_current_value_with_default_for_analyzers(result)
result[:analyzers].each do |analyzer|
analyzer[:variables].each do |entity|
entity[:value] = entity[:default_value] if entity[:default_value]
end
end
end
def populate_current_value_for_analyzers(result)
result[:analyzers].each do |analyzer|
analyzer[:enabled] = sast_default_analyzers.include?(analyzer[:name])
populate_current_value_for(analyzer, :variables)
end
end
def sast_template_attributes def sast_template_attributes
@sast_template_attributes ||= build_sast_attributes(sast_template_content) @sast_template_attributes ||= build_sast_attributes(sast_template_content)
end end
def sast_default_analyzers
@sast_default_analyzers ||= gitlab_ci_yml_attributes["SAST_DEFAULT_ANALYZERS"] || sast_template_attributes["SAST_DEFAULT_ANALYZERS"]
end
def gitlab_ci_yml_attributes def gitlab_ci_yml_attributes
@gitlab_ci_yml_attributes ||= begin @gitlab_ci_yml_attributes ||= begin
config_content = @project.repository.blob_data_at(@project.repository.root_ref_sha, ci_config_file) config_content = @project.repository.blob_data_at(@project.repository.root_ref_sha, ci_config_file)
......
---
title: Expose analyzer info for SAST Config
merge_request: 41825
author:
type: added
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe GitlabSchema.types['SastCiConfigurationAnalyzersEntity'] do RSpec.describe GitlabSchema.types['SastCiConfigurationAnalyzersEntity'] do
let(:fields) { %i[name label enabled description] } let(:fields) { %i[name label enabled description variables] }
it { expect(described_class.graphql_name).to eq('SastCiConfigurationAnalyzersEntity') } it { expect(described_class.graphql_name).to eq('SastCiConfigurationAnalyzersEntity') }
......
...@@ -12,6 +12,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do ...@@ -12,6 +12,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do
let(:sast_analyzer_image_tag) { configuration['global'][2] } let(:sast_analyzer_image_tag) { configuration['global'][2] }
let(:sast_pipeline_stage) { configuration['pipeline'][0] } let(:sast_pipeline_stage) { configuration['pipeline'][0] }
let(:sast_search_max_depth) { configuration['pipeline'][1] } let(:sast_search_max_depth) { configuration['pipeline'][1] }
let(:brakeman) { configuration['analyzers'][0] }
let(:sast_brakeman_level) { brakeman['variables'][0] }
it 'parses the configuration for SAST' do it 'parses the configuration for SAST' do
expect(secure_analyzers_prefix['default_value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers') expect(secure_analyzers_prefix['default_value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
...@@ -19,6 +21,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do ...@@ -19,6 +21,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do
expect(sast_analyzer_image_tag['default_value']).to eql('2') expect(sast_analyzer_image_tag['default_value']).to eql('2')
expect(sast_pipeline_stage['default_value']).to eql('test') expect(sast_pipeline_stage['default_value']).to eql('test')
expect(sast_search_max_depth['default_value']).to eql('4') expect(sast_search_max_depth['default_value']).to eql('4')
expect(brakeman['enabled']).to be(true)
expect(sast_brakeman_level['default_value']).to eql('1')
end end
context 'while populating current values of the entities' do context 'while populating current values of the entities' do
...@@ -30,6 +34,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do ...@@ -30,6 +34,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do
expect(sast_analyzer_image_tag['value']).to eql('2') expect(sast_analyzer_image_tag['value']).to eql('2')
expect(sast_pipeline_stage['value']).to eql('our_custom_security_stage') expect(sast_pipeline_stage['value']).to eql('our_custom_security_stage')
expect(sast_search_max_depth['value']).to eql('8') expect(sast_search_max_depth['value']).to eql('8')
expect(brakeman['enabled']).to be(false)
expect(sast_brakeman_level['value']).to eql('2')
end end
end end
...@@ -41,6 +47,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do ...@@ -41,6 +47,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do
expect(sast_analyzer_image_tag['value']).to eql('2') expect(sast_analyzer_image_tag['value']).to eql('2')
expect(sast_pipeline_stage['value']).to eql('test') expect(sast_pipeline_stage['value']).to eql('test')
expect(sast_search_max_depth['value']).to eql('4') expect(sast_search_max_depth['value']).to eql('4')
expect(brakeman['enabled']).to be(true)
expect(sast_brakeman_level['value']).to eql('1')
end end
end end
end end
......
...@@ -4,6 +4,7 @@ include: ...@@ -4,6 +4,7 @@ include:
variables: variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2" SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
SAST_EXCLUDED_PATHS: "spec, executables" SAST_EXCLUDED_PATHS: "spec, executables"
SAST_DEFAULT_ANALYZERS: "bandit, gosec"
stages: stages:
- our_custom_security_stage - our_custom_security_stage
...@@ -11,3 +12,4 @@ sast: ...@@ -11,3 +12,4 @@ sast:
stage: our_custom_security_stage stage: our_custom_security_stage
variables: variables:
SEARCH_MAX_DEPTH: 8 SEARCH_MAX_DEPTH: 8
SAST_BRAKEMAN_LEVEL: 2
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment