Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1b668e02bd
commit
f079dd371c
29 changed files with 442 additions and 61 deletions
|
@ -592,12 +592,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
|
|||
- ee/spec/services/requirements_management/update_requirement_service_spec.rb
|
||||
- ee/spec/services/resource_access_tokens/create_service_spec.rb
|
||||
- ee/spec/services/resource_access_tokens/revoke_service_spec.rb
|
||||
- ee/spec/services/status_page/publish_attachments_service_spec.rb
|
||||
- ee/spec/services/status_page/publish_details_service_spec.rb
|
||||
- ee/spec/services/status_page/publish_list_service_spec.rb
|
||||
- ee/spec/services/status_page/publish_service_spec.rb
|
||||
- ee/spec/services/status_page/trigger_publish_service_spec.rb
|
||||
- ee/spec/services/status_page/unpublish_details_service_spec.rb
|
||||
- ee/spec/services/todo_service_spec.rb
|
||||
- ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb
|
||||
- ee/spec/support/shared_examples/graphql/mutations/set_multiple_assignees_shared_examples.rb
|
||||
|
|
|
@ -46,6 +46,7 @@ export default {
|
|||
:loading-text="groupedSummaryText"
|
||||
:error-text="groupedSummaryText"
|
||||
:has-issues="shouldRenderIssuesList"
|
||||
track-action="users_expanding_testing_accessibility_report"
|
||||
class="mr-widget-section grouped-security-reports mr-report"
|
||||
>
|
||||
<template #body>
|
||||
|
|
|
@ -87,6 +87,7 @@ export default {
|
|||
:component="$options.componentNames.CodequalityIssueBody"
|
||||
:popover-options="codequalityPopover"
|
||||
:show-report-section-status-icon="false"
|
||||
track-action="users_expanding_testing_code_quality_report"
|
||||
class="js-codequality-widget mr-widget-border-top mr-report"
|
||||
>
|
||||
<template v-if="hasError" #sub-heading>{{ statusReason }}</template>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<script>
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import api from '~/api';
|
||||
import { __ } from '~/locale';
|
||||
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
|
||||
import Popover from '~/vue_shared/components/help_popover.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { status, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '../constants';
|
||||
import IssuesList from './issues_list.vue';
|
||||
|
||||
|
@ -14,6 +16,7 @@ export default {
|
|||
Popover,
|
||||
StatusIcon,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
props: {
|
||||
alwaysOpen: {
|
||||
type: Boolean,
|
||||
|
@ -98,6 +101,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
trackAction: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -164,6 +172,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
toggleCollapsed() {
|
||||
if (this.trackAction && this.glFeatures.usersExpandingWidgetsUsageData) {
|
||||
api.trackRedisHllUserEvent(this.trackAction);
|
||||
}
|
||||
|
||||
if (this.shouldEmitToggleEvent) {
|
||||
this.$emit('toggleEvent');
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ export default {
|
|||
:has-issues="false"
|
||||
class="mr-widget-border-top mr-report"
|
||||
data-testid="security-mr-widget"
|
||||
track-action="users_expanding_secure_security_report"
|
||||
>
|
||||
<template v-for="slot in $options.summarySlots" #[slot]>
|
||||
<span :key="slot">
|
||||
|
@ -212,6 +213,7 @@ export default {
|
|||
:has-issues="false"
|
||||
class="mr-widget-border-top mr-report"
|
||||
data-testid="security-mr-widget"
|
||||
track-action="users_expanding_secure_security_report"
|
||||
>
|
||||
<template #error>
|
||||
{{ $options.i18n.scansHaveRun }}
|
||||
|
|
|
@ -43,6 +43,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
|
||||
|
||||
# Usage data feature flags
|
||||
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
|
||||
|
||||
record_experiment_user(:invite_members_version_b)
|
||||
|
||||
experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
|
||||
|
|
|
@ -42,14 +42,14 @@ module TokenAuthenticatableStrategies
|
|||
return insecure_strategy.get_token(instance) if migrating?
|
||||
|
||||
encrypted_token = instance.read_attribute(encrypted_field)
|
||||
token = Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_token)
|
||||
token = EncryptionHelper.decrypt_token(encrypted_token)
|
||||
token || (insecure_strategy.get_token(instance) if optional?)
|
||||
end
|
||||
|
||||
def set_token(instance, token)
|
||||
raise ArgumentError unless token.present?
|
||||
|
||||
instance[encrypted_field] = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
|
||||
instance[encrypted_field] = EncryptionHelper.encrypt_token(token)
|
||||
instance[token_field] = token if migrating?
|
||||
instance[token_field] = nil if optional?
|
||||
token
|
||||
|
@ -85,10 +85,9 @@ module TokenAuthenticatableStrategies
|
|||
end
|
||||
|
||||
def find_by_encrypted_token(token, unscoped)
|
||||
nonce = Gitlab::CryptoHelper::AES256_GCM_IV_STATIC
|
||||
encrypted_value = Gitlab::CryptoHelper.aes256_gcm_encrypt(token, nonce: nonce)
|
||||
|
||||
relation(unscoped).find_by(encrypted_field => encrypted_value)
|
||||
encrypted_value = EncryptionHelper.encrypt_token(token)
|
||||
token_encrypted_with_static_iv = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
|
||||
relation(unscoped).find_by(encrypted_field => [encrypted_value, token_encrypted_with_static_iv])
|
||||
end
|
||||
|
||||
def insecure_strategy
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module TokenAuthenticatableStrategies
|
||||
class EncryptionHelper
|
||||
DYNAMIC_NONCE_IDENTIFIER = "|"
|
||||
NONCE_SIZE = 12
|
||||
|
||||
def self.encrypt_token(plaintext_token)
|
||||
Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext_token)
|
||||
end
|
||||
|
||||
def self.decrypt_token(token)
|
||||
return unless token
|
||||
|
||||
# The pattern of the token is "#{DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv_of_12_characters}"
|
||||
if token.start_with?(DYNAMIC_NONCE_IDENTIFIER) && token.size > NONCE_SIZE + DYNAMIC_NONCE_IDENTIFIER.size
|
||||
token_to_decrypt = token[1...-NONCE_SIZE]
|
||||
iv = token[-NONCE_SIZE..-1]
|
||||
|
||||
Gitlab::CryptoHelper.aes256_gcm_decrypt(token_to_decrypt, nonce: iv)
|
||||
else
|
||||
Gitlab::CryptoHelper.aes256_gcm_decrypt(token)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,18 +4,26 @@ module Issuable
|
|||
class DestroyService < IssuableBaseService
|
||||
def execute(issuable)
|
||||
if issuable.destroy
|
||||
delete_todos(issuable)
|
||||
issuable.update_project_counter_caches
|
||||
issuable.assignees.each(&:invalidate_cache_counts)
|
||||
after_destroy(issuable)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def delete_todos(issuable)
|
||||
actor = issuable.is_a?(Epic) ? issuable.resource_parent : issuable.resource_parent.group
|
||||
def after_destroy(issuable)
|
||||
delete_todos(issuable)
|
||||
issuable.update_project_counter_caches
|
||||
issuable.assignees.each(&:invalidate_cache_counts)
|
||||
end
|
||||
|
||||
if Feature.enabled?(:destroy_issuable_todos_async, actor, default_enabled: :yaml)
|
||||
def group_for(issuable)
|
||||
issuable.resource_parent
|
||||
end
|
||||
|
||||
def delete_todos(issuable)
|
||||
group = group_for(issuable)
|
||||
|
||||
if Feature.enabled?(:destroy_issuable_todos_async, group, default_enabled: :yaml)
|
||||
TodosDestroyer::DestroyedIssuableWorker
|
||||
.perform_async(issuable.id, issuable.class.name)
|
||||
else
|
||||
|
@ -26,3 +34,5 @@ module Issuable
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Issuable::DestroyService.prepend_if_ee('EE::Issuable::DestroyService')
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: users_expanding_widgets_usage_data
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
rollout_issue_url:
|
||||
milestone: '13.11'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: true
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.secure.users_expanding_secure_security_report_monthly
|
||||
description: Count of expanding the security report widget
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: group::static analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report_monthly
|
||||
description: Count of expanding the code quality widget
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: code_quality
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_report_monthly
|
||||
description: Count of expanding the accessibility report widget
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: accessibility_testing
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.secure.users_expanding_secure_security_report_weekly
|
||||
description: Count of expanding the security report widget
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: group::static analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report_weekly
|
||||
description: Count of expanding the code quality widget
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: code_quality
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_report_weekly
|
||||
description: Count of expanding the accessibility report widget
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: accessibility_testing
|
||||
value_type: number
|
||||
status: implemented
|
||||
milestone: '13.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -9872,6 +9872,30 @@ Status: `data_available`
|
|||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epics_usage.g_project_management_epic_destroyed_monthly`
|
||||
|
||||
Count of MAU destroying epics
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210413174710_g_project_management_epic_destroyed_monthly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epics_usage.g_project_management_epic_destroyed_weekly`
|
||||
|
||||
Count of WAU destroying epics
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210413174449_g_project_management_epic_destroyed_weekly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epics_usage.g_project_management_epic_issue_added_monthly`
|
||||
|
||||
Count of MAU adding issues to epics
|
||||
|
@ -13448,6 +13472,30 @@ Status: `data_available`
|
|||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.secure.users_expanding_secure_security_report_monthly`
|
||||
|
||||
Count of expanding the security report widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml)
|
||||
|
||||
Group: `group::static analysis`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.secure.users_expanding_secure_security_report_weekly`
|
||||
|
||||
Count of expanding the security report widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml)
|
||||
|
||||
Group: `group::static analysis`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.snippets.i_snippets_show_monthly`
|
||||
|
||||
Missing description
|
||||
|
@ -13880,6 +13928,54 @@ Status: `removed`
|
|||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.users_expanding_testing_accessibility_report_monthly`
|
||||
|
||||
Count of expanding the accessibility report widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.users_expanding_testing_accessibility_report_weekly`
|
||||
|
||||
Count of expanding the accessibility report widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.users_expanding_testing_code_quality_report_monthly`
|
||||
|
||||
Count of expanding the code quality widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.users_expanding_testing_code_quality_report_weekly`
|
||||
|
||||
Count of expanding the code quality widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.user_packages.i_package_composer_user_monthly`
|
||||
|
||||
Missing description
|
||||
|
|
|
@ -16,30 +16,17 @@ module Gitlab
|
|||
::Digest::SHA256.base64digest("#{value}#{salt}")
|
||||
end
|
||||
|
||||
def aes256_gcm_encrypt(value, nonce: nil)
|
||||
aes256_gcm_encrypt_using_static_nonce(value)
|
||||
def aes256_gcm_encrypt(value, nonce: AES256_GCM_IV_STATIC)
|
||||
encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value, iv: nonce))
|
||||
Base64.strict_encode64(encrypted_token)
|
||||
end
|
||||
|
||||
def aes256_gcm_decrypt(value)
|
||||
def aes256_gcm_decrypt(value, nonce: AES256_GCM_IV_STATIC)
|
||||
return unless value
|
||||
|
||||
nonce = AES256_GCM_IV_STATIC
|
||||
encrypted_token = Base64.decode64(value)
|
||||
decrypted_token = Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token, iv: nonce))
|
||||
decrypted_token
|
||||
end
|
||||
|
||||
def aes256_gcm_encrypt_using_static_nonce(value)
|
||||
create_encrypted_token(value, AES256_GCM_IV_STATIC)
|
||||
end
|
||||
|
||||
def read_only?
|
||||
Gitlab::Database.read_only?
|
||||
end
|
||||
|
||||
def create_encrypted_token(value, iv)
|
||||
encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value, iv: iv))
|
||||
Base64.strict_encode64(encrypted_token)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -460,3 +460,19 @@
|
|||
redis_slot: pipeline_authoring
|
||||
aggregation: weekly
|
||||
feature_flag: usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
|
||||
# Merge request widgets
|
||||
- name: users_expanding_secure_security_report
|
||||
redis_slot: secure
|
||||
category: secure
|
||||
aggregation: weekly
|
||||
feature_flag: users_expanding_widgets_usage_data
|
||||
- name: users_expanding_testing_code_quality_report
|
||||
redis_slot: testing
|
||||
category: testing
|
||||
aggregation: weekly
|
||||
feature_flag: users_expanding_widgets_usage_data
|
||||
- name: users_expanding_testing_accessibility_report
|
||||
redis_slot: testing
|
||||
category: testing
|
||||
aggregation: weekly
|
||||
feature_flag: users_expanding_widgets_usage_data
|
||||
|
|
|
@ -134,3 +134,9 @@
|
|||
redis_slot: project_management
|
||||
aggregation: daily
|
||||
feature_flag: track_epics_activity
|
||||
|
||||
- name: g_project_management_epic_destroyed
|
||||
category: epics_usage
|
||||
redis_slot: project_management
|
||||
aggregation: daily
|
||||
feature_flag: track_epics_activity
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.189.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "29.5.0",
|
||||
"@gitlab/ui": "29.6.0",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "^6.0.3-4",
|
||||
"@rails/ujs": "^6.0.3-4",
|
||||
|
|
|
@ -57,7 +57,6 @@ module DeprecationToolkitEnv
|
|||
%w[
|
||||
activerecord-6.0.3.6/lib/active_record/migration.rb
|
||||
activesupport-6.0.3.6/lib/active_support/cache.rb
|
||||
batch-loader-1.4.0/lib/batch_loader/graphql.rb
|
||||
carrierwave-1.3.1/lib/carrierwave/sanitized_file.rb
|
||||
activerecord-6.0.3.6/lib/active_record/relation.rb
|
||||
selenium-webdriver-3.142.7/lib/selenium/webdriver/firefox/driver.rb
|
||||
|
|
|
@ -20,15 +20,21 @@ RSpec.describe Gitlab::CryptoHelper do
|
|||
expect(encrypted).not_to include "\n"
|
||||
end
|
||||
|
||||
it 'does not save hashed token with iv value in database' do
|
||||
expect { described_class.aes256_gcm_encrypt('some-value') }.not_to change { TokenWithIv.count }
|
||||
end
|
||||
|
||||
it 'encrypts using static iv' do
|
||||
expect(Encryptor).to receive(:encrypt).with(described_class::AES256_GCM_OPTIONS.merge(value: 'some-value', iv: described_class::AES256_GCM_IV_STATIC)).and_return('hashed_value')
|
||||
|
||||
described_class.aes256_gcm_encrypt('some-value')
|
||||
end
|
||||
|
||||
context 'with provided iv' do
|
||||
let(:iv) { create_nonce }
|
||||
|
||||
it 'encrypts using provided iv' do
|
||||
expect(Encryptor).to receive(:encrypt).with(described_class::AES256_GCM_OPTIONS.merge(value: 'some-value', iv: iv)).and_return('hashed_value')
|
||||
|
||||
described_class.aes256_gcm_encrypt('some-value', nonce: iv)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.aes256_gcm_decrypt' do
|
||||
|
@ -46,10 +52,22 @@ RSpec.describe Gitlab::CryptoHelper do
|
|||
|
||||
expect(decrypted).to eq 'some-value'
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not save hashed token with iv value in database' do
|
||||
expect { described_class.aes256_gcm_decrypt(encrypted) }.not_to change { TokenWithIv.count }
|
||||
context 'when token was encrypted using random nonce' do
|
||||
let(:value) { 'random-value' }
|
||||
let(:iv) { create_nonce }
|
||||
let(:encrypted) { described_class.aes256_gcm_encrypt(value, nonce: iv) }
|
||||
|
||||
it 'correctly decrypts encrypted string' do
|
||||
decrypted = described_class.aes256_gcm_decrypt(encrypted, nonce: iv)
|
||||
|
||||
expect(decrypted).to eq value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_nonce
|
||||
::Digest::SHA256.hexdigest('my-value').bytes.take(TokenAuthenticatableStrategies::EncryptionHelper::NONCE_SIZE).pack('c*')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
'ci_templates',
|
||||
'quickactions',
|
||||
'pipeline_authoring',
|
||||
'epics_usage'
|
||||
'epics_usage',
|
||||
'secure'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1362,7 +1362,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
|
|||
|
||||
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
|
||||
let(:ineligible_total_categories) do
|
||||
%w[source_code ci_secrets_management incident_management_alerts snippets terraform incident_management_oncall]
|
||||
%w[source_code ci_secrets_management incident_management_alerts snippets terraform incident_management_oncall secure]
|
||||
end
|
||||
|
||||
context 'with redis_hll_tracking feature enabled' do
|
||||
|
|
|
@ -54,7 +54,7 @@ RSpec.describe ApplicationSetting, 'TokenAuthenticatable' do
|
|||
it 'persists new token as an encrypted string' do
|
||||
expect(subject).to eq settings.reload.runners_registration_token
|
||||
expect(settings.read_attribute('runners_registration_token_encrypted'))
|
||||
.to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
|
||||
.to eq TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token(subject)
|
||||
expect(settings).to be_persisted
|
||||
end
|
||||
|
||||
|
@ -243,7 +243,7 @@ RSpec.describe Ci::Build, 'TokenAuthenticatable' do
|
|||
it 'persists new token as an encrypted string' do
|
||||
build.ensure_token!
|
||||
|
||||
encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
|
||||
encrypted = TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token(build.token)
|
||||
|
||||
expect(build.read_attribute('token_encrypted')).to eq encrypted
|
||||
end
|
||||
|
|
|
@ -7,6 +7,10 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
let(:instance) { double(:instance) }
|
||||
|
||||
let(:encrypted) do
|
||||
TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token('my-value')
|
||||
end
|
||||
|
||||
let(:encrypted_with_static_iv) do
|
||||
Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value')
|
||||
end
|
||||
|
||||
|
@ -15,12 +19,25 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
|
||||
describe '#find_token_authenticatable' do
|
||||
context 'when using optional strategy' do
|
||||
context 'when encryption is required' do
|
||||
let(:options) { { encrypted: :required } }
|
||||
|
||||
it 'finds the encrypted resource by cleartext' do
|
||||
allow(model).to receive(:find_by)
|
||||
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
|
||||
.and_return('encrypted resource')
|
||||
|
||||
expect(subject.find_token_authenticatable('my-value'))
|
||||
.to eq 'encrypted resource'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when encryption is optional' do
|
||||
let(:options) { { encrypted: :optional } }
|
||||
|
||||
it 'finds the encrypted resource by cleartext' do
|
||||
allow(model).to receive(:find_by)
|
||||
.with('some_field_encrypted' => encrypted)
|
||||
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
|
||||
.and_return('encrypted resource')
|
||||
|
||||
expect(subject.find_token_authenticatable('my-value'))
|
||||
|
@ -33,7 +50,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
.and_return('plaintext resource')
|
||||
|
||||
allow(model).to receive(:find_by)
|
||||
.with('some_field_encrypted' => encrypted)
|
||||
.with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
|
||||
.and_return(nil)
|
||||
|
||||
expect(subject.find_token_authenticatable('my-value'))
|
||||
|
@ -41,7 +58,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when using migration strategy' do
|
||||
context 'when encryption is migrating' do
|
||||
let(:options) { { encrypted: :migrating } }
|
||||
|
||||
it 'finds the cleartext resource by cleartext' do
|
||||
|
@ -65,7 +82,27 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
|
||||
describe '#get_token' do
|
||||
context 'when using optional strategy' do
|
||||
context 'when encryption is required' do
|
||||
let(:options) { { encrypted: :required } }
|
||||
|
||||
it 'returns decrypted token when an encrypted with static iv token is present' do
|
||||
allow(instance).to receive(:read_attribute)
|
||||
.with('some_field_encrypted')
|
||||
.and_return(Gitlab::CryptoHelper.aes256_gcm_encrypt('my-test-value'))
|
||||
|
||||
expect(subject.get_token(instance)).to eq 'my-test-value'
|
||||
end
|
||||
|
||||
it 'returns decrypted token when an encrypted token is present' do
|
||||
allow(instance).to receive(:read_attribute)
|
||||
.with('some_field_encrypted')
|
||||
.and_return(encrypted)
|
||||
|
||||
expect(subject.get_token(instance)).to eq 'my-value'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when encryption is optional' do
|
||||
let(:options) { { encrypted: :optional } }
|
||||
|
||||
it 'returns decrypted token when an encrypted token is present' do
|
||||
|
@ -76,6 +113,14 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
expect(subject.get_token(instance)).to eq 'my-value'
|
||||
end
|
||||
|
||||
it 'returns decrypted token when an encrypted with static iv token is present' do
|
||||
allow(instance).to receive(:read_attribute)
|
||||
.with('some_field_encrypted')
|
||||
.and_return(Gitlab::CryptoHelper.aes256_gcm_encrypt('my-test-value'))
|
||||
|
||||
expect(subject.get_token(instance)).to eq 'my-test-value'
|
||||
end
|
||||
|
||||
it 'returns the plaintext token when encrypted token is not present' do
|
||||
allow(instance).to receive(:read_attribute)
|
||||
.with('some_field_encrypted')
|
||||
|
@ -89,7 +134,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when using migration strategy' do
|
||||
context 'when encryption is migrating' do
|
||||
let(:options) { { encrypted: :migrating } }
|
||||
|
||||
it 'returns cleartext token when an encrypted token is present' do
|
||||
|
@ -119,12 +164,22 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
|
||||
describe '#set_token' do
|
||||
context 'when using optional strategy' do
|
||||
context 'when encryption is required' do
|
||||
let(:options) { { encrypted: :required } }
|
||||
|
||||
it 'writes encrypted token and returns it' do
|
||||
expect(instance).to receive(:[]=)
|
||||
.with('some_field_encrypted', encrypted)
|
||||
|
||||
expect(subject.set_token(instance, 'my-value')).to eq 'my-value'
|
||||
end
|
||||
end
|
||||
context 'when encryption is optional' do
|
||||
let(:options) { { encrypted: :optional } }
|
||||
|
||||
it 'writes encrypted token and removes plaintext token and returns it' do
|
||||
expect(instance).to receive(:[]=)
|
||||
.with('some_field_encrypted', any_args)
|
||||
.with('some_field_encrypted', encrypted)
|
||||
expect(instance).to receive(:[]=)
|
||||
.with('some_field', nil)
|
||||
|
||||
|
@ -132,12 +187,12 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when using migration strategy' do
|
||||
context 'when encryption is migrating' do
|
||||
let(:options) { { encrypted: :migrating } }
|
||||
|
||||
it 'writes encrypted token and writes plaintext token' do
|
||||
expect(instance).to receive(:[]=)
|
||||
.with('some_field_encrypted', any_args)
|
||||
.with('some_field_encrypted', encrypted)
|
||||
expect(instance).to receive(:[]=)
|
||||
.with('some_field', 'my-value')
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TokenAuthenticatableStrategies::EncryptionHelper do
|
||||
let(:encrypted_token) { described_class.encrypt_token('my-value') }
|
||||
|
||||
describe '.encrypt_token' do
|
||||
it 'encrypts token' do
|
||||
expect(encrypted_token).not_to eq('my-value')
|
||||
end
|
||||
end
|
||||
|
||||
describe '.decrypt_token' do
|
||||
it 'decrypts token with static iv' do
|
||||
expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
|
||||
end
|
||||
|
||||
it 'decrypts token with dynamic iv' do
|
||||
iv = ::Digest::SHA256.hexdigest('my-value').bytes.take(described_class::NONCE_SIZE).pack('c*')
|
||||
token = Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value', nonce: iv)
|
||||
encrypted_token = "#{described_class::DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv}"
|
||||
|
||||
expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -907,10 +907,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||
|
||||
"@gitlab/ui@29.5.0":
|
||||
version "29.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.5.0.tgz#5f8cdf062ef69800c5a6f4a4871b7283f59de34a"
|
||||
integrity sha512-ebNNKZORRIoqQRF+tCaiS17pyt9qI46ULgyUYJkXHmwQKMUL0sqXRoPMPVK6T2snzMUnyNeKBMoMxTy5BiTnNA==
|
||||
"@gitlab/ui@29.6.0":
|
||||
version "29.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.6.0.tgz#5e8369d7aeab56edab570ef148dbc289b51901fc"
|
||||
integrity sha512-bomMDBzS/S+ztFgAC23oDjMEK3cFZ3UcKJGs3iKXtCTKIxtzXKrL0LWYxkidywIwWm9L+1udgsx/GTKoVW0ItQ==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
"@gitlab/vue-toasted" "^1.3.0"
|
||||
|
|
Loading…
Reference in a new issue