gitlab-security_report_schemas 0.1.0.min0.0.0.max0.0.0 → 0.1.0.min15.0.0.max15.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +27 -4
- data/RUNBOOK.md +28 -0
- data/Rakefile +14 -3
- data/gem_version +1 -1
- data/gitlab-security_report_schemas.gemspec +33 -0
- data/lib/gitlab/security_report_schemas/cli/schema_checker/remote_file.rb +9 -2
- data/lib/gitlab/security_report_schemas/cli/schema_downloader.rb +1 -3
- data/lib/gitlab/security_report_schemas/configuration.rb +27 -2
- data/lib/gitlab/security_report_schemas/release/bundler.rb +34 -0
- data/lib/gitlab/security_report_schemas/release/gemfile.rb +49 -0
- data/lib/gitlab/security_report_schemas/release/issue.rb +77 -0
- data/lib/gitlab/security_report_schemas/release/merge_request.rb +84 -0
- data/lib/gitlab/security_report_schemas/release/templates/issue_description.erb +13 -0
- data/lib/gitlab/security_report_schemas/release/workflow.rb +108 -0
- data/lib/gitlab/security_report_schemas/schema_ver.rb +7 -4
- data/lib/gitlab/security_report_schemas/version.rb +0 -2
- data/lib/gitlab/security_report_schemas.rb +7 -3
- data/schemas/15.0.0/cluster-image-scanning-report-format.json +946 -0
- data/schemas/15.0.0/container-scanning-report-format.json +880 -0
- data/schemas/15.0.0/coverage-fuzzing-report-format.json +836 -0
- data/schemas/15.0.0/dast-report-format.json +1241 -0
- data/schemas/15.0.0/dependency-scanning-report-format.json +944 -0
- data/schemas/15.0.0/sast-report-format.json +831 -0
- data/schemas/15.0.0/secret-detection-report-format.json +854 -0
- data/schemas/15.0.1/cluster-image-scanning-report-format.json +980 -0
- data/schemas/15.0.1/container-scanning-report-format.json +914 -0
- data/schemas/15.0.1/coverage-fuzzing-report-format.json +870 -0
- data/schemas/15.0.1/dast-report-format.json +1275 -0
- data/schemas/15.0.1/dependency-scanning-report-format.json +978 -0
- data/schemas/15.0.1/sast-report-format.json +865 -0
- data/schemas/15.0.1/secret-detection-report-format.json +888 -0
- data/schemas/15.0.2/cluster-image-scanning-report-format.json +980 -0
- data/schemas/15.0.2/container-scanning-report-format.json +912 -0
- data/schemas/15.0.2/coverage-fuzzing-report-format.json +870 -0
- data/schemas/15.0.2/dast-report-format.json +1275 -0
- data/schemas/15.0.2/dependency-scanning-report-format.json +978 -0
- data/schemas/15.0.2/sast-report-format.json +865 -0
- data/schemas/15.0.2/secret-detection-report-format.json +888 -0
- data/schemas/15.0.4/cluster-image-scanning-report-format.json +984 -0
- data/schemas/15.0.4/container-scanning-report-format.json +916 -0
- data/schemas/15.0.4/coverage-fuzzing-report-format.json +874 -0
- data/schemas/15.0.4/dast-report-format.json +1279 -0
- data/schemas/15.0.4/dependency-scanning-report-format.json +982 -0
- data/schemas/15.0.4/sast-report-format.json +869 -0
- data/schemas/15.0.4/secret-detection-report-format.json +893 -0
- data/schemas/15.0.5/cluster-image-scanning-report-format.json +1035 -0
- data/schemas/15.0.5/container-scanning-report-format.json +967 -0
- data/schemas/15.0.5/coverage-fuzzing-report-format.json +925 -0
- data/schemas/15.0.5/dast-report-format.json +1330 -0
- data/schemas/15.0.5/dependency-scanning-report-format.json +1033 -0
- data/schemas/15.0.5/sast-report-format.json +920 -0
- data/schemas/15.0.5/secret-detection-report-format.json +944 -0
- data/schemas/15.0.6/cluster-image-scanning-report-format.json +1035 -0
- data/schemas/15.0.6/container-scanning-report-format.json +967 -0
- data/schemas/15.0.6/coverage-fuzzing-report-format.json +925 -0
- data/schemas/15.0.6/dast-report-format.json +1330 -0
- data/schemas/15.0.6/dependency-scanning-report-format.json +1033 -0
- data/schemas/15.0.6/sast-report-format.json +920 -0
- data/schemas/15.0.6/secret-detection-report-format.json +944 -0
- data/schemas/15.0.7/cluster-image-scanning-report-format.json +1085 -0
- data/schemas/15.0.7/container-scanning-report-format.json +1017 -0
- data/schemas/15.0.7/coverage-fuzzing-report-format.json +975 -0
- data/schemas/15.0.7/dast-report-format.json +1380 -0
- data/schemas/15.0.7/dependency-scanning-report-format.json +1083 -0
- data/schemas/15.0.7/sast-report-format.json +970 -0
- data/schemas/15.0.7/secret-detection-report-format.json +994 -0
- data/schemas/15.1.0/cluster-image-scanning-report-format.json +1065 -0
- data/schemas/15.1.0/container-scanning-report-format.json +997 -0
- data/schemas/15.1.0/coverage-fuzzing-report-format.json +975 -0
- data/schemas/15.1.0/dast-report-format.json +1380 -0
- data/schemas/15.1.0/dependency-scanning-report-format.json +986 -0
- data/schemas/15.1.0/sast-report-format.json +970 -0
- data/schemas/15.1.0/secret-detection-report-format.json +994 -0
- data/schemas/15.1.1/cluster-image-scanning-report-format.json +1065 -0
- data/schemas/15.1.1/container-scanning-for-registry-report-format.json +0 -0
- data/schemas/15.1.1/container-scanning-report-format.json +998 -0
- data/schemas/15.1.1/coverage-fuzzing-report-format.json +975 -0
- data/schemas/15.1.1/dast-report-format.json +1380 -0
- data/schemas/15.1.1/dependency-scanning-report-format.json +986 -0
- data/schemas/15.1.1/sast-report-format.json +970 -0
- data/schemas/15.1.1/secret-detection-report-format.json +994 -0
- data/schemas/15.1.2/cluster-image-scanning-report-format.json +1190 -0
- data/schemas/15.1.2/container-scanning-report-format.json +1123 -0
- data/schemas/15.1.2/coverage-fuzzing-report-format.json +1100 -0
- data/schemas/15.1.2/dast-report-format.json +1505 -0
- data/schemas/15.1.2/dependency-scanning-report-format.json +1111 -0
- data/schemas/15.1.2/sast-report-format.json +1095 -0
- data/schemas/15.1.2/secret-detection-report-format.json +1119 -0
- data/schemas/15.1.3/cluster-image-scanning-report-format.json +1190 -0
- data/schemas/15.1.3/container-scanning-report-format.json +1123 -0
- data/schemas/15.1.3/coverage-fuzzing-report-format.json +1100 -0
- data/schemas/15.1.3/dast-report-format.json +1505 -0
- data/schemas/15.1.3/dependency-scanning-report-format.json +1111 -0
- data/schemas/15.1.3/sast-report-format.json +1095 -0
- data/schemas/15.1.3/secret-detection-report-format.json +1119 -0
- data/schemas/15.1.4/cluster-image-scanning-report-format.json +1190 -0
- data/schemas/15.1.4/container-scanning-report-format.json +1123 -0
- data/schemas/15.1.4/coverage-fuzzing-report-format.json +1100 -0
- data/schemas/15.1.4/dast-report-format.json +1505 -0
- data/schemas/15.1.4/dependency-scanning-report-format.json +1111 -0
- data/schemas/15.1.4/sast-report-format.json +1095 -0
- data/schemas/15.1.4/secret-detection-report-format.json +1119 -0
- data/supported_versions +12 -0
- metadata +112 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb0ee095cc1634e7242faa1990caf178447e8774e0c1027665388b24494c7b9c
|
4
|
+
data.tar.gz: eb1cd4245ced146a0d1f01769f1d60117e4b8cf36e51106abe6c7632096c0a40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d8aaaff8004ceb08b6cd1e1bfbde2b330ac45b66c3dc9c9d132b08d13dd2ea4137766ff4b87ce9789577f51df0ba3095e1a0f893341d9364cd88f19f160118b
|
7
|
+
data.tar.gz: a2c6dd7ff0729f43591b798e17adaf0830ece329356e200cd08c1cec772b47234b437705049b6dedce7ab587a0f41ef729c3048a5e5da5a0a883b28c26f8cbd1
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gitlab-security_report_schemas (0.1.0.
|
5
|
-
activesupport (>=
|
4
|
+
gitlab-security_report_schemas (0.1.0.min15.0.0.max15.1.4)
|
5
|
+
activesupport (>= 6, < 8)
|
6
6
|
json_schemer (~> 0.2.18)
|
7
7
|
|
8
8
|
GEM
|
@@ -91,4 +91,4 @@ DEPENDENCIES
|
|
91
91
|
shoulda-matchers (~> 5.0)
|
92
92
|
|
93
93
|
BUNDLED WITH
|
94
|
-
2.
|
94
|
+
2.5.14
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
[![pipeline status](https://gitlab.com/gitlab-org/
|
2
|
-
[![coverage report](https://gitlab.com/gitlab-org/
|
3
|
-
[![Latest Release](https://gitlab.com/gitlab-org/
|
1
|
+
[![pipeline status](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/badges/main/pipeline.svg)](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/-/commits/main)
|
2
|
+
[![coverage report](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/badges/main/coverage.svg)](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/-/commits/main)
|
3
|
+
[![Latest Release](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/-/badges/release.svg)](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/-/releases)
|
4
4
|
|
5
5
|
# Gitlab::SecurityReportSchemas
|
6
6
|
|
7
|
-
Rubygem for https://gitlab.com/gitlab-org/security-products/security-
|
7
|
+
Rubygem for https://gitlab.com/gitlab-org/security-products/security-report-schemas/
|
8
8
|
|
9
9
|
This gem provides a Ruby and command line interface to validate the report artifact generated by the security analyzers.
|
10
10
|
|
@@ -43,6 +43,29 @@ You can use the executable to check validity of your report artifact, like so;
|
|
43
43
|
bundle exec security-reports-schemas $FILE_PATH
|
44
44
|
```
|
45
45
|
|
46
|
+
### Environment variables
|
47
|
+
|
48
|
+
#### Credentials
|
49
|
+
|
50
|
+
| Key | Description |
|
51
|
+
|-----------------------------|-----------------------------------------------------------------------------------------------|
|
52
|
+
| `GITLAB_PUSH_ACCESS_TOKEN` | Own project access token used to push new schema versions. Requires `write_repository` scope. |
|
53
|
+
| `GITLAB_ISSUE_ACCESS_TOKEN` | Project access token used to create an issue on `gitlab-org/gitlab`. Requires `api` scopes. |
|
54
|
+
| `GEM_HOST_API_KEY` | rubygems.org API key |
|
55
|
+
|
56
|
+
#### Configuration
|
57
|
+
|
58
|
+
| Key | Default | Description |
|
59
|
+
|---------------------------|--------------------------------------------------------|----------------------------------------|
|
60
|
+
| `SCHEMAS_PATH` | `./schemas` | Schema storage location |
|
61
|
+
| `SCHEMA_PROJECT` | `gitlab-org/security-products/security-report-schemas` | Where to source schemas |
|
62
|
+
| `GITLAB_PROJECT` | `gitlab-org/gitlab` | Project to open MRs for |
|
63
|
+
| `ISSUE_TARGET_PROJECT_ID` | `278964` (`gitlab-org/gitlab`) | Project ID for which to open an issue. |
|
64
|
+
|
65
|
+
## Maintenance
|
66
|
+
|
67
|
+
See [`RUNBOOK.md`](./RUNBOOK.md) for solutions to common maintenance tasks.
|
68
|
+
|
46
69
|
## Development
|
47
70
|
|
48
71
|
### Updating the schemas
|
data/RUNBOOK.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Common maintenance tasks
|
2
|
+
|
3
|
+
### Problem
|
4
|
+
|
5
|
+
* an upstream [security-report-schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas) pipeline failed to trigger the release pipeline
|
6
|
+
* you want to add, remove or deprecate support for report schema versions
|
7
|
+
* you need to release a new version of the gem without altering version ranges,
|
8
|
+
because for example:
|
9
|
+
* an existing gem release has a bug, and the bugfix release needs to cover the
|
10
|
+
same version range.
|
11
|
+
* there were breaking changes to the gem's public API that must be released
|
12
|
+
for the currently supported version range.
|
13
|
+
|
14
|
+
### Solution
|
15
|
+
|
16
|
+
1. Open and merge an MR targeting the default branch which may:
|
17
|
+
* change the [`supported_versions`](../supported_versions) file to set the
|
18
|
+
report schema version range that the release should include.
|
19
|
+
* change the `Gitlab::SecurityReportSchemas::Version::GEM_VERSION` constant
|
20
|
+
to set the MAJOR.MINOR.PATCH version components of the resulting release.
|
21
|
+
2. Run a new pipeline for the default branch and set the `MANUAL_RELEASE` CI
|
22
|
+
variable.
|
23
|
+
3. Trigger the manual `manual-release` job in the resulting pipeline.
|
24
|
+
|
25
|
+
## Find the commit SHA for a RubyGem version
|
26
|
+
|
27
|
+
Before a rubygems.org release is created, a git tag referencing the full
|
28
|
+
v-prefixed release version is pushed, for example `v0.1.0.min15.0.0.max15.0.1`.
|
data/Rakefile
CHANGED
@@ -17,7 +17,9 @@ task :prepare_schemas, [:versions] do |_, args|
|
|
17
17
|
require "gitlab/security_report_schemas"
|
18
18
|
require "gitlab/security_report_schemas/cli/schema_downloader"
|
19
19
|
|
20
|
-
requested_versions = args
|
20
|
+
requested_versions = args.fetch(:versions, "").split.map do |ver|
|
21
|
+
Gitlab::SecurityReportSchemas::SchemaVer.new!(ver, fallback: false)
|
22
|
+
end
|
21
23
|
|
22
24
|
cleanup_schema_dir.then { schemas_to_prepare(requested_versions) }
|
23
25
|
.then { copy_new_schemas(_1) }
|
@@ -28,7 +30,7 @@ desc "Bundles the Security Report Schemas into the project and builds the gem"
|
|
28
30
|
task :prepare, %i[versions] => %i[prepare_schemas build]
|
29
31
|
|
30
32
|
desc "Checks the integrity of the schema files with upstream"
|
31
|
-
task :
|
33
|
+
task integrity_check: :prepare_schemas do
|
32
34
|
require "gitlab/security_report_schemas"
|
33
35
|
require "gitlab/security_report_schemas/cli/integrity_checker"
|
34
36
|
|
@@ -39,6 +41,15 @@ task :integrity_check do
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
44
|
+
namespace :release do
|
45
|
+
desc "Open patch Issue on gitlab-org/gitlab to update its Gemfile to use the current gem version"
|
46
|
+
task :issue do
|
47
|
+
require "gitlab/security_report_schemas"
|
48
|
+
|
49
|
+
Gitlab::SecurityReportSchemas::Release::Workflow.execute
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
42
53
|
def cleanup_schema_dir
|
43
54
|
puts "Cleaning the schemas directory..."
|
44
55
|
|
@@ -57,7 +68,7 @@ def schemas_to_prepare(requested_versions)
|
|
57
68
|
if requested_versions.empty?
|
58
69
|
puts "Preparing schemas from `supported_versions' file..."
|
59
70
|
else
|
60
|
-
puts
|
71
|
+
puts %(Preparing new schemas #{requested_versions.map(&:version).join(",")})
|
61
72
|
end
|
62
73
|
|
63
74
|
supported_versions + requested_versions
|
data/gem_version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.0.
|
1
|
+
0.1.0.min15.0.0.max15.1.4
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "gitlab-security_report_schemas"
|
5
|
+
spec.version = `cat gem_version`
|
6
|
+
spec.authors = ["GitLab"]
|
7
|
+
spec.email = ["gitlab_rubygems@gitlab.com"]
|
8
|
+
spec.license = "Nonstandard"
|
9
|
+
|
10
|
+
spec.summary = "Ruby gem for GitLab security report JSON schemas"
|
11
|
+
spec.homepage = "https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas"
|
12
|
+
spec.required_ruby_version = ">= 2.7.0"
|
13
|
+
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
|
16
|
+
# Specify which files should be added to the gem when it is released.
|
17
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
18
|
+
spec.files = Dir.chdir(__dir__) do
|
19
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
20
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Bundle the schemas into the gem
|
25
|
+
spec.files += `find schemas -type f`.split("\n")
|
26
|
+
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_dependency "activesupport", ">= 6", "< 8"
|
32
|
+
spec.add_dependency "json_schemer", "~> 0.2.18"
|
33
|
+
end
|
@@ -8,7 +8,6 @@ module Gitlab
|
|
8
8
|
class IntegrityChecker
|
9
9
|
# Represents the schema file located on GitLab.com
|
10
10
|
class RemoteFile < AbstractFile
|
11
|
-
SCHEMA_PROJECT_RAW_URL = "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/v%<version>s/dist/%<schema_file_name>s"
|
12
11
|
SCHEMA_FILE_NAME_REGEX = %r{./+(?<version>\d+\.\d+\.\d+)/(?<file_name>.+-report-format\.json)$}.freeze
|
13
12
|
|
14
13
|
private
|
@@ -22,7 +21,7 @@ module Gitlab
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def schema_url
|
25
|
-
format(
|
24
|
+
format(schema_project_raw_url, version: version, schema_file_name: schema_file_name)
|
26
25
|
end
|
27
26
|
|
28
27
|
def version
|
@@ -36,6 +35,14 @@ module Gitlab
|
|
36
35
|
def schema_file_components
|
37
36
|
@schema_file_components ||= schema_file.to_s.match(SCHEMA_FILE_NAME_REGEX).named_captures
|
38
37
|
end
|
38
|
+
|
39
|
+
def schema_project_raw_url
|
40
|
+
"#{schema_project_url}/-/raw/v%<version>s/dist/%<schema_file_name>s"
|
41
|
+
end
|
42
|
+
|
43
|
+
def schema_project_url
|
44
|
+
Gitlab::SecurityReportSchemas.configuration.schema_project_url
|
45
|
+
end
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
@@ -8,8 +8,6 @@ module Gitlab
|
|
8
8
|
module CLI
|
9
9
|
# Copies the schema for the given version to the project
|
10
10
|
class SchemaDownloader
|
11
|
-
SCHEMA_PROJECT_REPO = "git@gitlab.com:gitlab-org/security-products/security-report-schemas.git"
|
12
|
-
|
13
11
|
def self.download(version)
|
14
12
|
new(version).download
|
15
13
|
end
|
@@ -59,7 +57,7 @@ module Gitlab
|
|
59
57
|
end
|
60
58
|
|
61
59
|
def clone_repository
|
62
|
-
Git.clone(
|
60
|
+
Git.clone(Gitlab::SecurityReportSchemas.configuration.schema_repository, git_project_path)
|
63
61
|
end
|
64
62
|
|
65
63
|
def git_project_path
|
@@ -6,16 +6,41 @@ module Gitlab
|
|
6
6
|
class Configuration
|
7
7
|
OPTIONS = {
|
8
8
|
schemas_path: -> { SecurityReportSchemas.root_path.join("schemas") },
|
9
|
-
deprecated_versions: -> { [] }
|
9
|
+
deprecated_versions: -> { [] },
|
10
|
+
schema_project: -> { "gitlab-org/security-products/security-report-schemas" },
|
11
|
+
gitlab_project: -> { "gitlab-org/gitlab" },
|
12
|
+
issue_target_project_id: -> { "278964" }, # gitlab-org/gitlab
|
13
|
+
gitlab_issue_access_token: nil,
|
14
|
+
ci_server_host: nil
|
10
15
|
}.freeze
|
11
16
|
|
12
17
|
OPTIONS.each do |option, default_value|
|
13
18
|
define_method(option) do
|
14
|
-
instance_variable_get("@#{option}") || default_value
|
19
|
+
instance_variable_get("@#{option}") || ENV[option.upcase.to_s] || default_value&.call
|
15
20
|
end
|
16
21
|
|
17
22
|
attr_writer option
|
18
23
|
end
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
yield self if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def schema_project_url
|
30
|
+
"https://gitlab.com/#{schema_project}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def schema_repository
|
34
|
+
"#{schema_project_url}.git"
|
35
|
+
end
|
36
|
+
|
37
|
+
def gitlab_project_url
|
38
|
+
"https://gitlab.com/#{gitlab_project}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def gitlab_repository
|
42
|
+
"#{gitlab_project_url}.git"
|
43
|
+
end
|
19
44
|
end
|
20
45
|
end
|
21
46
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module SecurityReportSchemas
|
5
|
+
module Release
|
6
|
+
# Wrapper around bundle(1).
|
7
|
+
module Bundler
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def install!
|
11
|
+
run("bundle install")
|
12
|
+
end
|
13
|
+
|
14
|
+
def checksum!
|
15
|
+
run("bundle exec bundler-checksum init")
|
16
|
+
end
|
17
|
+
|
18
|
+
def verify_checksum!
|
19
|
+
run("bundle exec bundler-checksum verify")
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def run(command)
|
25
|
+
# Bundler modifies RUBYOPT and RUBYLIB which makes bundle(1) attempt
|
26
|
+
# to load from our gem environment instead of from the GitLab environment.
|
27
|
+
::Bundler.with_unbundled_env do
|
28
|
+
system(command) || raise("non-zero exit code: `#{command}`")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tempfile"
|
4
|
+
|
5
|
+
module Gitlab
|
6
|
+
module SecurityReportSchemas
|
7
|
+
module Release
|
8
|
+
# Changes or adds a dependency version to a Gemfile.
|
9
|
+
class Gemfile
|
10
|
+
SUBSTITUTION_REGEX_TEMPLATE = %{gem ['"]%s['"], ['"](.*)['"]}
|
11
|
+
FEATURE_CATEGORY = :vulnerability_management
|
12
|
+
|
13
|
+
def self.update!(workflow)
|
14
|
+
File.open(workflow.gemfile_path, "r+").tap do |file|
|
15
|
+
new(file).rewrite!(workflow.class::DEPENDENCY, workflow.gem_version)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :file
|
20
|
+
|
21
|
+
def initialize(file)
|
22
|
+
@file = file
|
23
|
+
end
|
24
|
+
|
25
|
+
private_class_method :new
|
26
|
+
|
27
|
+
def rewrite!(dependency, version)
|
28
|
+
contents = file.read
|
29
|
+
|
30
|
+
file.seek(0)
|
31
|
+
file.truncate(0)
|
32
|
+
file.puts(substituted_content(contents, dependency, version))
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def substituted_content(contents, dependency, version)
|
38
|
+
regex = Regexp.new(SUBSTITUTION_REGEX_TEMPLATE % dependency)
|
39
|
+
dep = "gem '#{dependency}', '#{version}'"
|
40
|
+
|
41
|
+
return contents.gsub!(regex, dep) if contents.match(regex)
|
42
|
+
|
43
|
+
contents.concat("#{dep}, feature_category: #{FEATURE_CATEGORY.inspect}")
|
44
|
+
contents.concat("\n") unless contents.end_with?("\n")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module SecurityReportSchemas
|
5
|
+
module Release
|
6
|
+
# GitLab Issue creation.
|
7
|
+
class Issue
|
8
|
+
API_ROOT = "https://gitlab.com/api/v4"
|
9
|
+
DESCRIPTION_TEMPLATE = "issue_description.erb"
|
10
|
+
|
11
|
+
def self.create!(workflow)
|
12
|
+
new(workflow).execute!
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :workflow
|
16
|
+
|
17
|
+
def initialize(workflow)
|
18
|
+
@workflow = workflow
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute!
|
22
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
http.use_ssl = true
|
24
|
+
|
25
|
+
case response = http.request(request)
|
26
|
+
when Net::HTTPSuccess then extract_url(JSON.parse(response.body))
|
27
|
+
else raise "Failed to create issue: #{response.code} -- #{response.message}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def uri
|
32
|
+
URI(File.join(API_ROOT, "projects", workflow.target_project_id.to_s, "issues"))
|
33
|
+
end
|
34
|
+
|
35
|
+
def body
|
36
|
+
{
|
37
|
+
title: workflow.commit_message,
|
38
|
+
description: description
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def headers
|
43
|
+
{
|
44
|
+
"Content-Type" => "application/json",
|
45
|
+
"Authorization" => "Bearer #{workflow.access_token}"
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def description
|
50
|
+
description_template.result_with_hash(gem_version: workflow.gem_version, patch: workflow.patch)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def request
|
56
|
+
Net::HTTP::Post.new(uri, headers).tap do |req|
|
57
|
+
req.body = body.to_json
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_url(body)
|
62
|
+
body["web_url"]
|
63
|
+
end
|
64
|
+
|
65
|
+
def description_template
|
66
|
+
ERB.new(File.read(description_template_path))
|
67
|
+
end
|
68
|
+
|
69
|
+
def description_template_path
|
70
|
+
Gitlab::SecurityReportSchemas.root_path.join(
|
71
|
+
"lib", "gitlab", "security_report_schemas", "release", "templates", DESCRIPTION_TEMPLATE
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "uri"
|
5
|
+
require "erb"
|
6
|
+
require "json"
|
7
|
+
|
8
|
+
module Gitlab
|
9
|
+
module SecurityReportSchemas
|
10
|
+
module Release
|
11
|
+
# GitLab merge request creation.
|
12
|
+
class MergeRequest
|
13
|
+
API_ROOT = "https://gitlab.com/api/v4"
|
14
|
+
DESCRIPTION_TEMPLATE = "mr_description.erb"
|
15
|
+
|
16
|
+
def self.create!(workflow)
|
17
|
+
new(workflow).execute!
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :workflow
|
21
|
+
|
22
|
+
def initialize(workflow)
|
23
|
+
@workflow = workflow
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute!
|
27
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
28
|
+
http.use_ssl = true
|
29
|
+
|
30
|
+
case response = http.request(request)
|
31
|
+
when Net::HTTPSuccess then extract_url(JSON.parse(response.body))
|
32
|
+
else raise "Failed to create merge request: #{response.code} -- #{response.message}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def uri
|
37
|
+
URI(File.join(API_ROOT, "projects", workflow.target_project_id.to_s, "merge_requests"))
|
38
|
+
end
|
39
|
+
|
40
|
+
def body
|
41
|
+
{
|
42
|
+
source_branch: workflow.branch_name,
|
43
|
+
target_branch: workflow.class::TARGET_BRANCH,
|
44
|
+
title: workflow.commit_message,
|
45
|
+
description: description
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def headers
|
50
|
+
{
|
51
|
+
"Content-Type" => "application/json",
|
52
|
+
"Authorization" => "Bearer #{workflow.access_token}"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def description
|
57
|
+
description_template.result_with_hash(gem_version: workflow.gem_version)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def request
|
63
|
+
Net::HTTP::Post.new(uri, headers).tap do |req|
|
64
|
+
req.body = body.to_json
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_url(body)
|
69
|
+
body["web_url"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def description_template
|
73
|
+
ERB.new(File.read(description_template_path))
|
74
|
+
end
|
75
|
+
|
76
|
+
def description_template_path
|
77
|
+
Gitlab::SecurityReportSchemas.root_path.join(
|
78
|
+
"lib", "gitlab", "security_report_schemas", "release", "templates", DESCRIPTION_TEMPLATE
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
This is an automatically generated Issue to update the version of [`gitlab-security_report_schemas`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-security_report_schemas/) to <%= gem_version %>.
|
2
|
+
|
3
|
+
### Patch
|
4
|
+
|
5
|
+
```diff
|
6
|
+
<%= patch %>
|
7
|
+
```
|
8
|
+
|
9
|
+
### Background
|
10
|
+
|
11
|
+
GitLab Secure schemas are used as part of [Security scanner integration](https://docs.gitlab.com/ee/development/integrations/secure.html) to ensure that reports produced by analyzers are able to be parsed successfully by GitLab. Each JSON report indicates which version of the Secure schema it conforms to. When the report is parsed, the file is validated using the appropriate schema and will be rejected if it does not succeed.
|
12
|
+
|
13
|
+
/label ~section::sec
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "git"
|
4
|
+
|
5
|
+
module Gitlab
|
6
|
+
module SecurityReportSchemas
|
7
|
+
module Release
|
8
|
+
# The release workflow that updates a GitLab repository's Gemfile
|
9
|
+
# dependency on this gem to an existing version published on rubygems.org
|
10
|
+
# and creates a merge request for the change.
|
11
|
+
class Workflow
|
12
|
+
DEPENDENCY = "gitlab-security_report_schemas"
|
13
|
+
COMMIT_MESSAGE = "Bump `#{DEPENDENCY}' to v%s"
|
14
|
+
BRANCH_NAME = "#{DEPENDENCY}-v%s"
|
15
|
+
TARGET_BRANCH = "master"
|
16
|
+
|
17
|
+
def self.execute(configuration = Gitlab::SecurityReportSchemas.configuration)
|
18
|
+
new(configuration).execute
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :configuration
|
22
|
+
|
23
|
+
def initialize(configuration)
|
24
|
+
@configuration = configuration
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute
|
28
|
+
gitlab_repository # ensure repository is cloned
|
29
|
+
|
30
|
+
update_gemfile!
|
31
|
+
install_dependencies!
|
32
|
+
|
33
|
+
issue_url = create_issue!
|
34
|
+
|
35
|
+
puts "Successfully created Issue: #{issue_url}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def patch
|
39
|
+
gitlab_repository.diff.patch
|
40
|
+
end
|
41
|
+
|
42
|
+
def gemfile_path
|
43
|
+
gitlab_repository_path.join("Gemfile")
|
44
|
+
end
|
45
|
+
|
46
|
+
def gem_version
|
47
|
+
File.read(gem_version_file).strip
|
48
|
+
end
|
49
|
+
|
50
|
+
def branch_name
|
51
|
+
BRANCH_NAME % gem_version
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit_message
|
55
|
+
COMMIT_MESSAGE % gem_version
|
56
|
+
end
|
57
|
+
|
58
|
+
def target_project_id
|
59
|
+
configuration.issue_target_project_id
|
60
|
+
end
|
61
|
+
|
62
|
+
def access_token
|
63
|
+
configuration.gitlab_issue_access_token
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def gitlab_repository
|
69
|
+
@gitlab_repository ||= if File.exist?(gitlab_repository_path)
|
70
|
+
Git.open(gitlab_repository_path)
|
71
|
+
else
|
72
|
+
Git.clone(configuration.gitlab_repository, gitlab_repository_path, depth: 1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def update_gemfile!
|
77
|
+
Gitlab::SecurityReportSchemas::Release::Gemfile.update!(self)
|
78
|
+
end
|
79
|
+
|
80
|
+
def install_dependencies!
|
81
|
+
bundle do
|
82
|
+
install!
|
83
|
+
checksum!
|
84
|
+
verify_checksum!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def bundle(&block)
|
89
|
+
Dir.chdir(gitlab_repository_path) do
|
90
|
+
Gitlab::SecurityReportSchemas::Release::Bundler.module_eval(&block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_issue!
|
95
|
+
Gitlab::SecurityReportSchemas::Release::Issue.create!(self)
|
96
|
+
end
|
97
|
+
|
98
|
+
def gitlab_repository_path
|
99
|
+
Gitlab::SecurityReportSchemas.root_path.join("tmp", "gitlab")
|
100
|
+
end
|
101
|
+
|
102
|
+
def gem_version_file
|
103
|
+
Gitlab::SecurityReportSchemas.root_path.join("gem_version")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -10,17 +10,20 @@ module Gitlab
|
|
10
10
|
|
11
11
|
include Comparable
|
12
12
|
|
13
|
-
def self.new!(version)
|
13
|
+
def self.new!(version, fallback: true)
|
14
14
|
return SecurityReportSchemas.supported_versions.last if version.blank?
|
15
|
-
raise InvalidSchemaVersion, version unless version.match(VALID_SCHEMA_FORMAT)
|
16
15
|
|
17
|
-
|
16
|
+
raise InvalidSchemaVersion, version unless version.match?(VALID_SCHEMA_FORMAT)
|
17
|
+
|
18
|
+
instance = new(version)
|
19
|
+
|
20
|
+
fallback ? instance.itself_or_fallback : instance
|
18
21
|
end
|
19
22
|
|
20
23
|
attr_reader :version
|
21
24
|
|
22
25
|
def initialize(version)
|
23
|
-
@version = version
|
26
|
+
@version = version[VALID_SCHEMA_FORMAT]
|
24
27
|
end
|
25
28
|
|
26
29
|
def itself_or_fallback
|