Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-07-08 00:17:29 +00:00
parent c608e2662b
commit ffb0a89712
33 changed files with 1019 additions and 4 deletions

View File

@ -2,6 +2,12 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 14.0.4 (2021-07-07)
### Security (1 change)
- [Disable file and network premailer strategies](gitlab-org/security/gitlab@4af58e3d8ee1b25048f34208db6e685cf0bf1411) ([merge request](gitlab-org/security/gitlab!1544))
## 14.0.3 (2021-07-06)
### Fixed (7 changes)
@ -684,6 +690,12 @@ entry.
- [Add missing metrics information](gitlab-org/gitlab@89cd7fe3b95323e635b2d73e08549b2e6153dc4d) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61772/edit))
- [Track usage of the resolve UI](gitlab-org/gitlab@35c8e30fce288cecefcf2f7c0077d4608e696519) ([merge request](gitlab-org/gitlab!61654))
## 13.12.8 (2021-07-07)
### Security (1 change)
- [Disable file and network premailer strategies](gitlab-org/security/gitlab@ee69d6d6950bb116cb31523ca805e78af431c25c) ([merge request](gitlab-org/security/gitlab!1545))
## 13.12.7 (2021-07-05)
### Fixed (2 changes)
@ -1357,6 +1369,12 @@ entry.
- Change wording for design management upload. !61782
## 13.11.7 (2021-07-07)
### Security (1 change)
- [Disable file and network premailer strategies](gitlab-org/security/gitlab@511ed3746b48a26e95c851f76ac6fdcd44c28fd8) ([merge request](gitlab-org/security/gitlab!1546))
## 13.11.6 (2021-07-01)
### Added (1 change)

View File

@ -1 +1 @@
8cc6bb1ffb6830fa416c8d0e32f9edebf6573730
ed9300c34897316f98e93d909b964828cb4e5879

View File

@ -0,0 +1,55 @@
<script>
import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
import Papa from 'papaparse';
export default {
components: {
GlTable,
GlAlert,
GlLoadingIcon,
},
props: {
csv: {
type: String,
required: true,
},
},
data() {
return {
items: [],
errorMessage: null,
loading: true,
};
},
mounted() {
const parsed = Papa.parse(this.csv, { skipEmptyLines: true });
this.items = parsed.data;
if (parsed.errors.length) {
this.errorMessage = parsed.errors.map((e) => e.message).join('. ');
}
this.loading = false;
},
};
</script>
<template>
<div class="container-fluid md gl-mt-3 gl-mb-3">
<div v-if="loading" class="gl-text-center loading">
<gl-loading-icon class="gl-mt-5" size="lg" />
</div>
<div v-else>
<gl-alert v-if="errorMessage" variant="danger" :dismissible="false">
{{ errorMessage }}
</gl-alert>
<gl-table
:empty-text="__('No CSV data to display.')"
:items="items"
:fields="$options.fields"
show-empty
thead-class="gl-display-none"
/>
</div>
</div>
</template>

View File

@ -0,0 +1,17 @@
import Vue from 'vue';
import CsvViewer from './csv_viewer.vue';
export default () => {
const el = document.getElementById('js-csv-viewer');
return new Vue({
el,
render(createElement) {
return createElement(CsvViewer, {
props: {
csv: el.dataset.data,
},
});
},
});
};

View File

@ -0,0 +1,3 @@
import renderCSV from './csv';
export default renderCSV;

View File

@ -21,6 +21,8 @@ const loadRichBlobViewer = (type) => {
return import(/* webpackChunkName: 'notebook_viewer' */ '../notebook_viewer');
case 'openapi':
return import(/* webpackChunkName: 'openapi_viewer' */ '../openapi_viewer');
case 'csv':
return import(/* webpackChunkName: 'csv_viewer' */ '../csv_viewer');
case 'pdf':
return import(/* webpackChunkName: 'pdf_viewer' */ '../pdf_viewer');
case 'sketch':

View File

@ -373,8 +373,6 @@ class ProjectsController < Projects::ApplicationController
.new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
.map(&:present)
Events::RenderService.new(current_user).execute(@events, atom_request: request.format.atom?)
end
# rubocop: enable CodeReuse/ActiveRecord

View File

@ -27,6 +27,7 @@ class Blob < SimpleDelegator
# type. LFS pointers to `.stl` files are assumed to always be the binary kind,
# and use the `BinarySTL` viewer.
RICH_VIEWERS = [
BlobViewer::CSV,
BlobViewer::Markup,
BlobViewer::Notebook,
BlobViewer::SVG,

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
module BlobViewer
class CSV < Base
include Rich
include ClientSide
self.binary = false
self.extensions = %w(csv)
self.partial_name = 'csv'
self.switcher_icon = 'table'
end
end

View File

@ -0,0 +1 @@
.file-content#js-csv-viewer{ data: { data: viewer.blob.data } }

View File

@ -7,5 +7,6 @@ Premailer::Rails.config.merge!(
remove_comments: true,
remove_ids: false,
remove_scripts: false,
output_encoding: 'US-ASCII'
output_encoding: 'US-ASCII',
strategies: [:asset_pipeline]
)

View File

@ -49,6 +49,7 @@ Rails.autoloaders.each do |autoloader|
'ldap_key' => 'LDAPKey',
'mr_note' => 'MRNote',
'pdf' => 'PDF',
'csv' => 'CSV',
'rsa_token' => 'RSAToken',
'san_extension' => 'SANExtension',
'sca' => 'SCA',

113
doc/api/packages/helm.md Normal file
View File

@ -0,0 +1,113 @@
---
stage: Package
group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Helm API
This is the API documentation for [Helm](../../user/packages/helm_repository/index.md).
WARNING:
This API is used by the Helm-related package clients such as [Helm](https://helm.sh/)
and [`helm-push`](https://github.com/chartmuseum/helm-push/#readme),
and is generally not meant for manual consumption. This API is under development and is not ready
for production use due to limited functionality.
For instructions on how to upload and install Helm packages from the GitLab
Package Registry, see the [Helm registry documentation](../../user/packages/helm_repository/index.md).
NOTE:
These endpoints do not adhere to the standard API authentication methods.
See the [Helm registry documentation](../../user/packages/helm_repository/index.md)
for details on which headers and token types are supported.
## Enable the Helm API
The Helm API for GitLab is behind a feature flag that is disabled by default. GitLab
administrators with access to the GitLab Rails console can enable this API for your instance.
To enable it:
```ruby
Feature.enable(:helm_packages)
```
To disable it:
```ruby
Feature.disable(:helm_packages)
```
## Download a chart index
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62757) in GitLab 14.1.
Download a chart index:
```plaintext
GET projects/:id/packages/helm/:channel/index.yaml
```
| Attribute | Type | Required | Description |
| --------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the project. |
| `channel` | string | yes | Helm repository channel. |
```shell
curl --user <username>:<personal_access_token> \
https://gitlab.example.com/api/v4/projects/1/packages/helm/stable/index.yaml
```
Write the output to a file:
```shell
curl --user <username>:<personal_access_token> \
https://gitlab.example.com/api/v4/projects/1/packages/helm/stable/index.yaml \
--remote-name
```
## Download a chart
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014) in GitLab 14.0.
Download a chart:
```plaintext
GET projects/:id/packages/helm/:channel/charts/:file_name.tgz
```
| Attribute | Type | Required | Description |
| ----------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the project. |
| `channel` | string | yes | Helm repository channel. |
| `file_name` | string | yes | Chart file name. |
```shell
curl --user <username>:<personal_access_token> \
https://gitlab.example.com/api/v4/projects/1/packages/helm/stable/charts/mychart.tgz \
--remote-name
```
## Upload a chart
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64814) in GitLab 14.1.
Upload a chart:
```plaintext
POST projects/:id/packages/helm/api/:channel/charts
```
| Attribute | Type | Required | Description |
| --------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the project. |
| `channel` | string | yes | Helm repository channel. |
| `chart` | file | yes | Chart (as `multipart/form-data`). |
```shell
curl --request POST \
--form 'chart=@mychart.tgz' \
--user <username>:<personal_access_token> \
https://gitlab.example.com/api/v4/projects/1/packages/helm/api/stable/charts
```

View File

@ -39,6 +39,12 @@ Now when a user tries to push a commit with a message `Bugfix`, their push is
declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
is accepted.
The error message includes the rejected commit's SHA.
To resolve such errors, commit again with a matching message,
[rebase and reword](../topics/git/numerous_undo_possibilities_in_git/index.md#how-to-change-history),
or [amend](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---amend)
that commit's message locally.
### Restrict branch names
If your company has a strict policy for branch names, you may want the branches to start

View File

@ -314,6 +314,19 @@ The version of the chart used to provision PostgreSQL:
GitLab encourages users to [migrate their database](upgrading_postgresql.md)
to the newer PostgreSQL.
### Customize values for PostgreSQL Helm Chart
> [Introduced](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/113) in auto-deploy-image v2, in GitLab 13.8.
To set custom values, do one of the following:
- Add a file named `.gitlab/auto-deploy-postgres-values.yaml` to your repository. If found, this
file is used automatically. This file is used by default for PostgreSQL Helm upgrades.
- Add a file with a different name or path to the repository, and set the
`POSTGRES_HELM_UPGRADE_VALUES_FILE` [environment variable](#database) with the path
and name.
- Set the `POSTGRES_HELM_UPGRADE_EXTRA_ARGS` [environment variable](#database).
### Using external PostgreSQL database providers
While Auto DevOps provides out-of-the-box support for a PostgreSQL container for
@ -408,6 +421,8 @@ The following table lists CI/CD variables related to the database.
| `POSTGRES_PASSWORD` | The PostgreSQL password. Defaults to `testing-password`. Set it to use a custom password. |
| `POSTGRES_DB` | The PostgreSQL database name. Defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/index.md#predefined-cicd-variables). Set it to use a custom database name. |
| `POSTGRES_VERSION` | Tag for the [`postgres` Docker image](https://hub.docker.com/_/postgres) to use. Defaults to `9.6.16` for tests and deployments as of GitLab 13.0 (previously `9.6.2`). If `AUTO_DEVOPS_POSTGRES_CHANNEL` is set to `1`, deployments uses the default version `9.6.2`. |
| `POSTGRES_HELM_UPGRADE_VALUES_FILE` | In GitLab 13.8 and later, and when using [auto-deploy-image v2](upgrading_auto_deploy_dependencies.md), this variable allows the `helm upgrade` values file for PostgreSQL to be overridden. Defaults to `.gitlab/auto-deploy-postgres-values.yaml`. |
| `POSTGRES_HELM_UPGRADE_EXTRA_ARGS` | In GitLab 13.8 and later, and when using [auto-deploy-image v2](upgrading_auto_deploy_dependencies.md), this variable allows extra PostgreSQL options in `helm upgrade` commands when deploying the application. Note that using quotes doesn't prevent word splitting. |
### Disable jobs

View File

@ -0,0 +1,80 @@
---
stage: Package
group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Helm charts in the Package Registry **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18997) in GitLab 14.1.
WARNING:
The Helm package registry for GitLab is under development and isn't ready for production use due to
limited functionality.
Publish Helm packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
For documentation of the specific API endpoints that Helm package manager
clients use, see the [Helm API documentation](../../../api/packages/helm.md).
## Enable the Helm repository feature
Helm repository support is still a work in progress. It's gated behind a feature flag that's
**disabled by default**. [GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
can opt to enable it.
To enable it:
```ruby
Feature.enable(:helm_packages)
```
To disable it:
```ruby
Feature.disable(:helm_packages)
```
## Build a Helm package
Creating a Helm package is documented [in the Helm documentation](https://helm.sh/docs/intro/using_helm/#creating-your-own-charts).
## Authenticate to the Helm repository
To authenticate to the Helm repository, you need either:
- A [personal access token](../../../api/index.md#personalproject-access-tokens).
- A [deploy token](../../project/deploy_tokens/index.md).
- A [CI/CD job token](../../../api/index.md#gitlab-cicd-job-token).
## Publish a package
Once built, a chart can be uploaded to the `stable` channel with `curl` or `helm-push`:
- With `curl`:
```shell
curl --request POST \
--form 'chart=@mychart.tgz' \
--user <username>:<personal_access_token> \
https://gitlab.example.com/api/v4/projects/1/packages/helm/api/stable/charts
```
- With the [`helm-push`](https://github.com/chartmuseum/helm-push/#readme) plugin:
```shell
helm repo add --username <username> --password <personal_access_token> project-1 https://gitlab.example.com/api/v4/projects/1/packages/helm/stable
helm push mychart.tgz project-1
```
## Install a package
To install the latest version of a chart, use the following command:
```shell
helm repo add project-1 https://gitlab.example.com/api/v4/projects/1/packages/helm/stable
helm install my-release project-1/mychart
```
See [Using Helm](https://helm.sh/docs/intro/using_helm/) for more information.

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Analyzer
attr_reader :id, :name, :version, :vendor
def initialize(id:, name:, version:, vendor:)
@id = id
@name = name
@version = version
@vendor = vendor
end
end
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
module Concerns
module FingerprintPathFromFile
extend ActiveSupport::Concern
def fingerprint_path
File.basename(file_path.to_s)
end
end
end
end
end
end
end

View File

@ -0,0 +1,69 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Identifier
attr_reader :external_id
attr_reader :external_type
attr_reader :fingerprint
attr_reader :name
attr_reader :url
def initialize(external_id:, external_type:, name:, url: nil)
@external_id = external_id
@external_type = external_type
@name = name
@url = url
@fingerprint = generate_fingerprint
end
def key
fingerprint
end
def to_hash
%i[
external_id
external_type
fingerprint
name
url
].each_with_object({}) do |key, hash|
hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend
end
end
def ==(other)
other.external_type == external_type &&
other.external_id == external_id
end
def type_identifier?
cwe? || wasc?
end
def cve?
external_type.to_s.casecmp?('cve')
end
def cwe?
external_type.to_s.casecmp?('cwe')
end
def wasc?
external_type.to_s.casecmp?('wasc')
end
private
def generate_fingerprint
Digest::SHA1.hexdigest("#{external_type}:#{external_id}")
end
end
end
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Link
attr_accessor :name, :url
def initialize(name: nil, url: nil)
@name = name
@url = url
end
def to_hash
{
name: name,
url: url
}.compact
end
end
end
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class ScannedResource
include Gitlab::Utils::StrongMemoize
attr_reader :request_method
attr_reader :request_uri
delegate :scheme, :host, :port, :path, :query, to: :request_uri, prefix: :url
def initialize(uri, request_method)
raise ArgumentError unless uri.is_a?(URI)
@request_method = request_method
@request_uri = uri
end
end
end
end
end
end

View File

@ -0,0 +1,60 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Scanner
ANALYZER_ORDER = {
"bundler_audit" => 1,
"retire.js" => 2,
"gemnasium" => 3,
"gemnasium-maven" => 3,
"gemnasium-python" => 3,
"bandit" => 1,
"semgrep" => 2
}.freeze
attr_accessor :external_id, :name, :vendor, :version
alias_method :key, :external_id
def initialize(external_id:, name:, vendor:, version:)
@external_id = external_id
@name = name
@vendor = vendor
@version = version
end
def to_hash
{
external_id: external_id.to_s,
name: name.to_s,
vendor: vendor.presence
}.compact
end
def ==(other)
other.external_id == external_id
end
def <=>(other)
sort_keys <=> other.sort_keys
end
protected
def sort_keys
@sort_keys ||= [order, external_id, name, vendor]
end
private
def order
ANALYZER_ORDER.fetch(external_id, Float::INFINITY)
end
end
end
end
end
end

View File

@ -22029,6 +22029,9 @@ msgstr ""
msgid "No %{providerTitle} repositories found"
msgstr ""
msgid "No CSV data to display."
msgstr ""
msgid "No Epic"
msgstr ""

View File

@ -148,6 +148,7 @@
"monaco-editor-webpack-plugin": "^4.0.0",
"monaco-yaml": "^2.5.1",
"mousetrap": "1.6.5",
"papaparse": "^5.3.1",
"pdfjs-dist": "^2.0.943",
"pikaday": "^1.8.0",
"popper.js": "^1.16.1",

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
FactoryBot.define do
factory :ci_reports_security_identifier, class: '::Gitlab::Ci::Reports::Security::Identifier' do
external_id { 'PREDICTABLE_RANDOM' }
external_type { 'find_sec_bugs_type' }
name { "#{external_type}-#{external_id}" }
skip_create
initialize_with do
::Gitlab::Ci::Reports::Security::Identifier.new(**attributes)
end
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
FactoryBot.define do
factory :ci_reports_security_link, class: '::Gitlab::Ci::Reports::Security::Link' do
name { 'CVE-2020-0202' }
url { 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0202' }
skip_create
initialize_with do
::Gitlab::Ci::Reports::Security::Link.new(**attributes)
end
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
FactoryBot.define do
factory :ci_reports_security_scanner, class: '::Gitlab::Ci::Reports::Security::Scanner' do
external_id { 'find_sec_bugs' }
name { 'Find Security Bugs' }
vendor { 'Security Scanner Vendor' }
version { '1.0.0' }
skip_create
initialize_with do
::Gitlab::Ci::Reports::Security::Scanner.new(**attributes)
end
end
factory :ci_reports_security_scan, class: '::Gitlab::Ci::Reports::Security::Scan' do
status { 'success' }
type { 'sast' }
start_time { 'placeholder' }
end_time { 'placeholder' }
skip_create
initialize_with do
::Gitlab::Ci::Reports::Security::Scan.new(attributes)
end
end
end

View File

@ -0,0 +1,75 @@
import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { getAllByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import CSVViewer from '~/blob/csv/csv_viewer.vue';
const validCsv = 'one,two,three';
const brokenCsv = '{\n "json": 1,\n "key": [1, 2, 3]\n}';
describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
let wrapper;
const createComponent = ({ csv = validCsv, mountFunction = shallowMount } = {}) => {
wrapper = mountFunction(CSVViewer, {
propsData: {
csv,
},
});
};
const findCsvTable = () => wrapper.findComponent(GlTable);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAlert = () => wrapper.findComponent(GlAlert);
afterEach(() => {
wrapper.destroy();
});
it('should render loading spinner', () => {
createComponent();
expect(findLoadingIcon().props()).toMatchObject({
size: 'lg',
});
});
describe('when the CSV contains errors', () => {
it('should render alert', async () => {
createComponent({ csv: brokenCsv });
await nextTick;
expect(findAlert().props()).toMatchObject({
variant: 'danger',
});
});
});
describe('when the CSV contains no errors', () => {
it('should not render alert', async () => {
createComponent();
await nextTick;
expect(findAlert().exists()).toBe(false);
});
it('renders the CSV table with the correct attributes', async () => {
createComponent();
await nextTick;
expect(findCsvTable().attributes()).toMatchObject({
'empty-text': 'No CSV data to display.',
items: validCsv,
});
});
it('renders the CSV table with the correct content', async () => {
createComponent({ mountFunction: mount });
await nextTick;
expect(getAllByRole(wrapper.element, 'row', { name: /One/i })).toHaveLength(1);
expect(getAllByRole(wrapper.element, 'row', { name: /Two/i })).toHaveLength(1);
expect(getAllByRole(wrapper.element, 'row', { name: /Three/i })).toHaveLength(1);
});
});
});

View File

@ -0,0 +1,125 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Identifier do
using RSpec::Parameterized::TableSyntax
describe '#initialize' do
subject { described_class.new(**params) }
let(:params) do
{
external_type: 'brakeman_warning_code',
external_id: '107',
name: 'Brakeman Warning Code 107',
url: 'https://brakemanscanner.org/docs/warning_types/cross_site_scripting/'
}
end
context 'when all params are given' do
it 'initializes an instance' do
expect { subject }.not_to raise_error
expect(subject).to have_attributes(
external_type: 'brakeman_warning_code',
external_id: '107',
fingerprint: 'aa2254904a69148ad14b6ac5db25b355da9c987f',
name: 'Brakeman Warning Code 107',
url: 'https://brakemanscanner.org/docs/warning_types/cross_site_scripting/'
)
end
end
%i[external_type external_id name].each do |attribute|
context "when attribute #{attribute} is missing" do
before do
params.delete(attribute)
end
it 'raises an error' do
expect { subject }.to raise_error(ArgumentError)
end
end
end
end
describe '#key' do
let(:identifier) { create(:ci_reports_security_identifier) }
subject { identifier.key }
it 'returns fingerprint' do
is_expected.to eq(identifier.fingerprint)
end
end
describe '#type_identifier?' do
where(:external_type, :expected_result) do
'cve' | false
'foo' | false
'cwe' | true
'wasc' | true
end
with_them do
let(:identifier) { create(:ci_reports_security_identifier, external_type: external_type) }
subject { identifier.type_identifier? }
it { is_expected.to be(expected_result) }
end
end
describe 'external type check methods' do
where(:external_type, :is_cve?, :is_cwe?, :is_wasc?) do
'Foo' | false | false | false
'Cve' | true | false | false
'Cwe' | false | true | false
'Wasc' | false | false | true
end
with_them do
let(:identifier) { create(:ci_reports_security_identifier, external_type: external_type) }
it 'returns correct result for the type check method' do
expect(identifier.cve?).to be(is_cve?)
expect(identifier.cwe?).to be(is_cwe?)
expect(identifier.wasc?).to be(is_wasc?)
end
end
end
describe '#to_hash' do
let(:identifier) { create(:ci_reports_security_identifier) }
subject { identifier.to_hash }
it 'returns expected hash' do
is_expected.to eq({
external_type: identifier.external_type,
external_id: identifier.external_id,
fingerprint: identifier.fingerprint,
name: identifier.name,
url: identifier.url
})
end
end
describe '#==' do
where(:type_1, :id_1, :type_2, :id_2, :equal, :case_name) do
'CVE' | '2018-1234' | 'CVE' | '2018-1234' | true | 'when external_type and external_id are equal'
'CVE' | '2018-1234' | 'brakeman_code' | '2018-1234' | false | 'when external_type is different'
'CVE' | '2018-1234' | 'CVE' | '2019-6789' | false | 'when external_id is different'
end
with_them do
let(:identifier_1) { create(:ci_reports_security_identifier, external_type: type_1, external_id: id_1) }
let(:identifier_2) { create(:ci_reports_security_identifier, external_type: type_2, external_id: id_2) }
it "returns #{params[:equal]}" do
expect(identifier_1 == identifier_2).to eq(equal)
end
end
end
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Link do
subject(:security_link) { described_class.new(name: 'CVE-2020-0202', url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0202') }
describe '#initialize' do
context 'when all params are given' do
it 'initializes an instance' do
expect { subject }.not_to raise_error
expect(subject).to have_attributes(
name: 'CVE-2020-0202',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0202'
)
end
end
describe '#to_hash' do
it 'returns expected hash' do
expect(security_link.to_hash).to eq(
{
name: 'CVE-2020-0202',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0202'
}
)
end
end
end
end

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::ScannedResource do
let(:url) { 'http://example.com:3001/1?foo=bar' }
let(:request_method) { 'GET' }
context 'when the URI is not a URI' do
subject { ::Gitlab::Ci::Reports::Security::ScannedResource.new(url, request_method) }
it 'raises an error' do
expect { subject }.to raise_error(ArgumentError)
end
end
context 'when the URL is valid' do
subject { ::Gitlab::Ci::Reports::Security::ScannedResource.new(URI.parse(url), request_method) }
it 'sets the URL attributes' do
expect(subject.request_method).to eq(request_method)
expect(subject.request_uri.to_s).to eq(url)
expect(subject.url_scheme).to eq('http')
expect(subject.url_host).to eq('example.com')
expect(subject.url_port).to eq(3001)
expect(subject.url_path).to eq('/1')
expect(subject.url_query).to eq('foo=bar')
end
end
end

View File

@ -0,0 +1,145 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Scanner do
describe '#initialize' do
subject { described_class.new(**params) }
let(:params) do
{
external_id: 'brakeman',
name: 'Brakeman',
vendor: 'GitLab',
version: '1.0.1'
}
end
context 'when all params are given' do
it 'initializes an instance' do
expect { subject }.not_to raise_error
expect(subject).to have_attributes(
external_id: 'brakeman',
name: 'Brakeman',
vendor: 'GitLab'
)
end
end
%i[external_id name].each do |attribute|
context "when attribute #{attribute} is missing" do
before do
params.delete(attribute)
end
it 'raises an error' do
expect { subject }.to raise_error(ArgumentError)
end
end
end
end
describe '#key' do
let(:scanner) { create(:ci_reports_security_scanner) }
subject { scanner.key }
it 'returns external_id' do
is_expected.to eq(scanner.external_id)
end
end
describe '#to_hash' do
let(:scanner) { create(:ci_reports_security_scanner) }
subject { scanner.to_hash }
it 'returns expected hash' do
is_expected.to eq({
external_id: scanner.external_id,
name: scanner.name,
vendor: scanner.vendor
})
end
context 'when vendor is not defined' do
let(:scanner) { create(:ci_reports_security_scanner, vendor: nil) }
it 'returns expected hash' do
is_expected.to eq({
external_id: scanner.external_id,
name: scanner.name
})
end
end
end
describe '#==' do
using RSpec::Parameterized::TableSyntax
where(:id_1, :id_2, :equal, :case_name) do
'brakeman' | 'brakeman' | true | 'when external_id is equal'
'brakeman' | 'bandit' | false | 'when external_id is different'
end
with_them do
let(:scanner_1) { create(:ci_reports_security_scanner, external_id: id_1) }
let(:scanner_2) { create(:ci_reports_security_scanner, external_id: id_2) }
it "returns #{params[:equal]}" do
expect(scanner_1 == scanner_2).to eq(equal)
end
end
end
describe '#<=>' do
using RSpec::Parameterized::TableSyntax
let(:scanner_1) { create(:ci_reports_security_scanner, **scanner_1_attributes) }
let(:scanner_2) { create(:ci_reports_security_scanner, **scanner_2_attributes) }
subject { scanner_1 <=> scanner_2 }
context 'when the `external_id` of the scanners are different' do
where(:scanner_1_attributes, :scanner_2_attributes, :expected_comparison_result) do
{ external_id: 'bundler_audit', name: 'foo', vendor: 'bar' } | { external_id: 'retire.js', name: 'foo', vendor: 'bar' } | -1
{ external_id: 'retire.js', name: 'foo', vendor: 'bar' } | { external_id: 'gemnasium', name: 'foo', vendor: 'bar' } | -1
{ external_id: 'gemnasium', name: 'foo', vendor: 'bar' } | { external_id: 'gemnasium-maven', name: 'foo', vendor: 'bar' } | -1
{ external_id: 'gemnasium-maven', name: 'foo', vendor: 'bar' } | { external_id: 'gemnasium-python', name: 'foo', vendor: 'bar' } | -1
{ external_id: 'gemnasium-python', name: 'foo', vendor: 'bar' } | { external_id: 'bandit', name: 'foo', vendor: 'bar' } | 1
{ external_id: 'bandit', name: 'foo', vendor: 'bar' } | { external_id: 'semgrep', name: 'foo', vendor: 'bar' } | -1
{ external_id: 'semgrep', name: 'foo', vendor: 'bar' } | { external_id: 'unknown', name: 'foo', vendor: 'bar' } | -1
end
with_them do
it { is_expected.to eq(expected_comparison_result) }
end
end
context 'when the `external_id` of the scanners are equal' do
context 'when the `name` of the scanners are different' do
where(:scanner_1_attributes, :scanner_2_attributes, :expected_comparison_result) do
{ external_id: 'gemnasium', name: 'a', vendor: 'bar' } | { external_id: 'gemnasium', name: 'b', vendor: 'bar' } | -1
{ external_id: 'gemnasium', name: 'd', vendor: 'bar' } | { external_id: 'gemnasium', name: 'c', vendor: 'bar' } | 1
end
with_them do
it { is_expected.to eq(expected_comparison_result) }
end
end
context 'when the `name` of the scanners are equal' do
where(:scanner_1_attributes, :scanner_2_attributes, :expected_comparison_result) do
{ external_id: 'gemnasium', name: 'foo', vendor: 'a' } | { external_id: 'gemnasium', name: 'foo', vendor: 'a' } | 0 # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
{ external_id: 'gemnasium', name: 'foo', vendor: 'a' } | { external_id: 'gemnasium', name: 'foo', vendor: 'b' } | -1
{ external_id: 'gemnasium', name: 'foo', vendor: 'b' } | { external_id: 'gemnasium', name: 'foo', vendor: 'a' } | 1
end
with_them do
it { is_expected.to eq(expected_comparison_result) }
end
end
end
end
end

View File

@ -9154,6 +9154,11 @@ pako@~1.0.2, pako@~1.0.5:
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==
papaparse@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.1.tgz#770b7a9124d821d4b2132132b7bd7dce7194b5b1"
integrity sha512-Dbt2yjLJrCwH2sRqKFFJaN5XgIASO9YOFeFP8rIBRG2Ain8mqk5r1M6DkfvqEVozVcz3r3HaUGw253hA1nLIcA==
parallel-transform@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"