Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-03-07 03:10:20 +00:00
parent 7e99f6b9fc
commit 3e0178f80c
17 changed files with 441 additions and 83 deletions

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
module WorkItems
class WorkItemDeletedEvent < Gitlab::EventStore::Event
def schema
{
'type' => 'object',
'required' => %w[id namespace_id],
'properties' => {
'id' => { 'type' => 'integer' },
'namespace_id' => { 'type' => 'integer' },
'work_item_parent_id' => { 'type' => 'integer' }
}
}
end
end
end

View File

@ -8,10 +8,23 @@ module WorkItems
end
if super
publish_event(work_item)
::ServiceResponse.success
else
::ServiceResponse.error(message: work_item.errors.full_messages)
end
end
private
def publish_event(work_item)
Gitlab::EventStore.publish(
WorkItems::WorkItemDeletedEvent.new(data: {
id: work_item.id,
namespace_id: work_item.namespace_id,
work_item_parent_id: work_item.work_item_parent&.id
}.tap(&:compact_blank!))
)
end
end
end

View File

@ -0,0 +1,9 @@
---
migration_job_name: BackfillHasIssuesForExternalIssueLinks
description: Backfill has_issues value in vulnerability_reads for Vulnerabilities which have an ExternalIssueLink record
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146643
milestone: '16.10'
queued_migration_version: 20240305120551
finalize_after: '2024-04-15'
finalized_by: # version of the migration that finalized this BBM

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class QueueBackfillHasIssuesForExternalIssueLinks < Gitlab::Database::Migration[2.2]
milestone '16.10'
MIGRATION = "BackfillHasIssuesForExternalIssueLinks"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 10_000
SUB_BATCH_SIZE = 200
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
queue_batched_background_migration(
MIGRATION,
:vulnerability_reads,
:vulnerability_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :vulnerability_reads, :vulnerability_id, [])
end
end

View File

@ -0,0 +1 @@
eca08fbea06ecb67ed56674a2c365e1e8a1fb5414845a916a2479165195a586b

View File

@ -388,6 +388,7 @@ Note the following:
- `.pipeline-policy-pre`at the beginning of the pipeline, before the `.pre` stage.
- `.pipeline-policy-test` after the `test` stage. If the `test` stage does not exist, it will be injected after the `build` stage. If the `build` stage does not exist, it will be injected at the beginning of the pipeline after the `.pre` stage.
- `.pipeline-policy-post` at the very end of the pipeline, after the .post stage.
- Jobs without a stage are assigned to the `.pipeline-policy-test` stage by default.
#### Example security policies project

View File

@ -288,6 +288,36 @@ To review the results of an import:
1. To see the details of a failed import, select the **See failures** link on any import with a **Failed** or **Partially completed** status.
1. If the import has a **Partially completed** or **Complete** status, to see which items were and were not imported, select **Details**.
## Cancel a running import
To cancel a running import:
1. Start a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session)
on the destination GitLab instance.
1. Find the last import by running the following command. Replace `USER_ID` with the user ID of the user that started the import:
```ruby
bulk_import = BulkImport.where(user_id: USER_ID).last
```
1. Cause the import and all items associated with it to fail by running the following command:
```ruby
bulk_import.entities.each do |entity|
entity.trackers.each do |tracker|
tracker.batches.each(&:fail_op!)
end
entity.trackers.each(&:fail_op!)
entity.fail_op!
end
bulk_import.fail_op!
```
Cancelling a `bulk_import` doesn't stop workers that are exporting the project on the source instance, but:
- Prevents the destination from asking for more projects to be exported.
- Prevents the target from making more API calls to the source.
## Migrated group items
The group items that are migrated depend on the version of GitLab you use on the destination. To determine if a
@ -502,28 +532,6 @@ entities.where(status: [-1]).pluck(:destination_name, :destination_namespace, :s
You can also see all migrated entities with any failures related to them using an
[API endpoint](../../../api/bulk_imports.md#list-all-group-or-project-migrations-entities).
### Remove cancelled imports
Sometime you might have to cancel an import. Cancelled imports don't clean up after themselves so you must delete
the imported items yourself. To delete the import by direct transfer that was most recently run:
1. Start a [Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
1. Find the last import by running the following command. Replace `USER_ID` with the user ID of the user that ran the
cancelled import:
```ruby
bulk_import = BulkImport.find_by(user_id: USER_ID).last
```
1. Delete the last import, including all items associated with it, by running the following command:
```ruby
bulk_import.destroy!
```
Any items associated with the import by direct transfer, including merge requests, projects, and issues, should be
deleted.
### Stale imports
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352985) in GitLab 14.10.

View File

@ -16,6 +16,7 @@ module Backup
@remote_storage = Backup::RemoteStorage.new(progress: progress, options: options)
end
# @return [Boolean] whether all tasks succeeded
def create
# Deprecation: Using backup_id (ENV['BACKUP']) to specify previous backup was deprecated in 15.0
previous_backup = options.previous_backup || options.backup_id
@ -27,28 +28,32 @@ module Backup
"and are not included in this backup. You will need these files to restore a backup.\n" \
"Please back them up manually.".color(:red)
puts_time "Backup #{backup_id} is done."
true
end
# @param [Gitlab::Backup::Tasks::Task] task
# @return [Boolean] whether the task succeeded
def run_create_task(task)
build_backup_information
unless task.enabled?
puts_time "Dumping #{task.human_name} ... ".color(:blue) + "[DISABLED]".color(:cyan)
return
return true
end
if options.skip_task?(task.id)
puts_time "Dumping #{task.human_name} ... ".color(:blue) + "[SKIPPED]".color(:cyan)
return
return true
end
puts_time "Dumping #{task.human_name} ... ".color(:blue)
task.backup!(backup_path, backup_id)
puts_time "Dumping #{task.human_name} ... ".color(:blue) + "done".color(:green)
true
rescue Backup::DatabaseBackupError, Backup::FileBackupError => e
puts_time "Dumping #{task.human_name} failed: #{e.message}".color(:red)
false
end
def restore

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillHasIssuesForExternalIssueLinks < BatchedMigrationJob
operation_name :backfill_has_issues_for_external_issue_links
scope_to ->(relation) { relation.where(has_issues: false) }
feature_category :vulnerability_management
UPDATE_SQL = <<~SQL
UPDATE
vulnerability_reads
SET
has_issues = true
FROM
(%<subquery>s) as sub_query
WHERE
vulnerability_reads.vulnerability_id = sub_query.vulnerability_id
SQL
def perform
each_sub_batch do |sub_batch|
update_query = update_query_for(sub_batch)
connection.execute(update_query)
end
end
private
def update_query_for(sub_batch)
subquery = sub_batch.joins("
INNER JOIN vulnerability_external_issue_links ON
vulnerability_reads.vulnerability_id =
vulnerability_external_issue_links.vulnerability_id")
format(UPDATE_SQL, subquery: subquery.to_sql)
end
end
end
end

View File

@ -9,8 +9,8 @@ module Tasks
def self.create_backup
lock_backup do
::Gitlab::TaskHelpers.warn_user_is_not_gitlab
::Backup::Manager.new(backup_progress).create
success = ::Backup::Manager.new(backup_progress).create
exit 1 unless success
end
end
@ -26,8 +26,8 @@ module Tasks
lock_backup do
backup_manager = ::Backup::Manager.new(backup_progress)
task = backup_manager.find_task(task_id)
backup_manager.run_create_task(task)
success = backup_manager.run_create_task(task)
exit 1 unless success
end
end

View File

@ -27,44 +27,66 @@ RSpec.describe Backup::Manager, feature_category: :backup_restore do
end
describe '#run_create_task' do
let(:terraform_state) do
Backup::Tasks::TerraformState.new(progress: progress, options: options)
describe 'other task' do
let(:terraform_state) do
Backup::Tasks::TerraformState.new(progress: progress, options: options)
.tap { |state| allow(state).to receive(:target).and_return(target) }
end
let(:target) { instance_double(Backup::Targets::Target) }
let(:backup_tasks) do
{ 'terraform_state' => terraform_state }
end
it 'runs the provided task' do
expect(target).to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... ')
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... done')
subject.run_create_task(terraform_state)
end
context 'when disabled' do
it 'does not run the task and informs the user' do
allow(terraform_state).to receive(:enabled).and_return(false)
expect(target).not_to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... [DISABLED]')
subject.run_create_task(terraform_state)
end
end
context 'when skipped' do
it 'does not run the task and informs the user' do
stub_env('SKIP', 'terraform_state')
expect(target).not_to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... [SKIPPED]')
subject.run_create_task(terraform_state)
end
end
end
end
describe 'database task' do
let(:backup_state) do
Backup::Tasks::Database.new(progress: progress, options: options)
.tap { |state| allow(state).to receive(:target).and_return(target) }
end
let(:target) { instance_double(Backup::Targets::Target) }
let(:backup_tasks) do
{ 'terraform_state' => terraform_state }
backup_state
end
it 'runs the provided task' do
expect(target).to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... ')
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... done')
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping database ... ')
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping database ... done')
subject.run_create_task(terraform_state)
end
context 'when disabled' do
it 'does not run the task and informs the user' do
allow(terraform_state).to receive(:enabled).and_return(false)
expect(target).not_to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... [DISABLED]')
subject.run_create_task(terraform_state)
end
end
context 'when skipped' do
it 'does not run the task and informs the user' do
stub_env('SKIP', 'terraform_state')
expect(target).not_to receive(:dump)
expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping terraform states ... [SKIPPED]')
subject.run_create_task(terraform_state)
end
subject.run_create_task(backup_tasks)
end
end

View File

@ -0,0 +1,170 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillHasIssuesForExternalIssueLinks, feature_category: :vulnerability_management do
let(:users) { table(:users) }
let(:user) { create_user(email: "test1@example.com", username: "test1") }
let(:namespaces) { table(:namespaces) }
let(:namespace) { namespaces.create!(name: 'test-1', path: 'test-1', owner_id: user.id) }
let(:projects) { table(:projects) }
let(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) }
let(:members) { table(:members) }
let!(:membership) do
members.create!(access_level: 50, source_id: project.id, source_type: "Project", user_id: user.id, state: 0,
notification_level: 3, type: "ProjectMember", member_namespace_id: namespace.id)
end
let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
let(:vulnerability_scanners) { table(:vulnerability_scanners) }
let(:scanner) { create_scanner(project_id: project.id) }
let(:vulnerability_findings) { table(:vulnerability_occurrences) }
let(:vulnerabilities) { table(:vulnerabilities) }
let(:vulnerability_reads) { table(:vulnerability_reads) }
let(:vulnerability_external_issue_links) { table(:vulnerability_external_issue_links) }
let(:vulnerability) do
create_full_vulnerability(project)
end
let(:vulnerability_read) do
vulnerability_reads.find_by(vulnerability_id: vulnerability.id)
end
let!(:external_issue_link) do
vulnerability_external_issue_links.create!(
author_id: user.id,
vulnerability_id: vulnerability.id,
external_project_key: "TEST",
external_issue_key: "123"
)
end
subject(:perform_migration) do
described_class.new(
start_id: vulnerability_reads.first.vulnerability_id,
end_id: vulnerability_reads.last.vulnerability_id,
batch_table: :vulnerability_reads,
batch_column: :vulnerability_id,
sub_batch_size: vulnerability_reads.count,
pause_ms: 0,
connection: ActiveRecord::Base.connection
).perform
end
it 'sets has_issues of an existing record' do
expect { perform_migration }.to change { vulnerability_read.reload.has_issues }.from(false).to(true)
end
context 'when there exists a record with has_issues' do
let(:vulnerability_2) do
create_full_vulnerability(project, read_overrides: { has_issues: true })
end
let(:vulnerability_read_2) { vulnerability_reads.find_by(vulnerability_id: vulnerability_2.id) }
it 'does not modify existing records with has_issues' do
expect { perform_migration }.not_to change { vulnerability_read_2.reload.has_merge_request }.from(false)
end
end
private
def create_full_vulnerability(project, finding_overrides: {}, vulnerability_overrides: {}, read_overrides: {})
finding = create_finding(project, finding_overrides)
vulnerability = create_vulnerability(vulnerability_overrides.merge(finding_id: finding.id))
create_vulnerability_read(vulnerability, finding, read_overrides)
vulnerability
end
def create_scanner(project, overrides = {})
random_scanner_uuid = SecureRandom.uuid
attrs = {
project_id: project.id,
external_id: "test_vulnerability_scanner-#{random_scanner_uuid})",
name: "Test Vulnerabilities::Scanner #{random_scanner_uuid}"
}.merge(overrides)
vulnerability_scanners.create!(attrs)
end
def create_identifier(project, overrides = {})
attrs = {
project_id: project.id,
external_id: "CVE-2018-1234",
external_type: "CVE",
name: "CVE-2018-1234",
fingerprint: SecureRandom.hex(20)
}.merge(overrides)
vulnerability_identifiers.create!(attrs)
end
def create_finding(project, overrides = {})
attrs = {
project_id: project.id,
scanner_id: create_scanner(project).id,
severity: 5, # medium
confidence: 2, # unknown,
report_type: 99, # generic
primary_identifier_id: create_identifier(project).id,
project_fingerprint: SecureRandom.hex(20),
location_fingerprint: SecureRandom.hex(20),
uuid: SecureRandom.uuid,
name: "CVE-2018-1234",
raw_metadata: "{}",
metadata_version: "test:1.0"
}.merge(overrides)
vulnerability_findings.create!(attrs)
end
def create_vulnerability(overrides = {})
attrs = {
project_id: project.id,
author_id: user.id,
title: 'test',
severity: 1,
confidence: 1,
report_type: 1,
state: 1,
detected_at: Time.zone.now
}.merge(overrides)
vulnerabilities.create!(attrs)
end
def create_vulnerability_read(vulnerability, finding, overrides = {})
attrs = {
project_id: vulnerability.project_id,
vulnerability_id: vulnerability.id,
scanner_id: finding.scanner_id,
severity: vulnerability.severity,
report_type: vulnerability.report_type,
state: vulnerability.state,
uuid: finding.uuid
}.merge(overrides)
vulnerability_reads.create!(attrs)
end
def create_user(overrides = {})
attrs = {
email: "test@example.com",
notification_email: "test@example.com",
name: "test",
username: "test",
state: "active",
projects_limit: 10
}.merge(overrides)
users.create!(attrs)
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillHasIssuesForExternalIssueLinks, feature_category: :vulnerability_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :vulnerability_reads,
column_name: :vulnerability_id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
}
end
end
end

View File

@ -11,17 +11,29 @@ RSpec.describe WorkItems::DeleteService, feature_category: :team_planning do
let(:user) { guest }
let(:service) { described_class.new(container: project, current_user: user) }
before_all do
# note necessary to test note removal as part of work item deletion
create(:note, project: project, noteable: work_item)
end
describe '#execute' do
subject(:result) { described_class.new(container: project, current_user: user).execute(work_item) }
subject(:result) { service.execute(work_item) }
context 'when user can delete the work item' do
it { is_expected.to be_success }
it 'publish WorkItems::WorkItemDeletedEvent' do
expect { service.execute(work_item) }
.to publish_event(::WorkItems::WorkItemDeletedEvent)
.with({
id: work_item.id,
namespace_id: work_item.namespace_id,
work_item_parent_id: work_item.work_item_parent&.id
}.tap(&:compact_blank!))
end
context 'when work item exists at the group level' do
let_it_be(:work_item) { create(:work_item, :group_level, namespace: group) }
@ -63,6 +75,11 @@ RSpec.describe WorkItems::DeleteService, feature_category: :team_planning do
it 'returns error messages' do
expect(result.errors).to contain_exactly('User not authorized to delete work item')
end
it 'does not publish WorkItems::WorkItemDeletedEvent' do
expect { service.execute(work_item) }
.not_to publish_event(::WorkItems::WorkItemDeletedEvent)
end
end
end
end

View File

@ -361,7 +361,9 @@ RSpec.describe 'gitlab:backup namespace rake tasks', :delete, feature_category:
end
it "raises an error with message" do
expect { run_rake_task(rake_task) }.to output(Regexp.new(error.message)).to_stdout_from_any_process
expect do
expect { run_rake_task(rake_task) }.to raise_error(SystemExit)
end.to output(Regexp.new(error.message)).to_stdout_from_any_process
end
end
end

View File

@ -3,7 +3,7 @@ module gitlab.com/gitlab-org/gitlab/workhorse
go 1.20
require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0
github.com/BurntSushi/toml v1.3.2
github.com/alecthomas/chroma/v2 v2.12.0
github.com/aws/aws-sdk-go v1.50.7
@ -32,7 +32,7 @@ require (
golang.org/x/tools v0.18.0
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.32.0
honnef.co/go/tools v0.4.6
honnef.co/go/tools v0.4.7
)
require (
@ -45,12 +45,12 @@ require (
cloud.google.com/go/storage v1.35.1 // indirect
cloud.google.com/go/trace v1.10.4 // indirect
contrib.go.opencensus.io/exporter/stackdriver v0.13.14 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
github.com/DataDog/datadog-go v4.4.0+incompatible // indirect
github.com/DataDog/sketches-go v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
@ -69,7 +69,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/google/wire v0.5.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
@ -88,7 +88,7 @@ require (
github.com/oklog/ulid/v2 v2.0.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/philhofer/fwd v1.1.1 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect

View File

@ -60,21 +60,21 @@ cloud.google.com/go/trace v1.10.4/go.mod h1:Nso99EDIK8Mj5/zmB+iGr9dosS/bzWCJ8wGm
contrib.go.opencensus.io/exporter/stackdriver v0.13.14 h1:zBakwHardp9Jcb8sQHcHpXy/0+JIb1M8KjigCJzx7+4=
contrib.go.opencensus.io/exporter/stackdriver v0.13.14/go.mod h1:5pSSGY0Bhuk7waTHuDf4aQ8D2DrhgETRo9fy6k3Xlzc=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 h1:c4k2FIYIh4xtwqrQwV0Ct1v5+ehlNXj5NI/MWVsiTkQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2/go.mod h1:5FDJtLEO/GxwNgUxbwrY3LP0pEoThTQJtk2oysdXHxM=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1 h1:AMf7YbZOZIW5b66cXNHMWWT/zkjhz5+a+k/3x40EO7E=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.1/go.mod h1:uwfk06ZBcvL/g4VHNjurPfVln9NMbsk2XIZxJ+hu81k=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0 h1:IfFdxTUDiV58iZqPKgyWiz4X4fCxZeQ1pTQPImLYXpY=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0/go.mod h1:SUZc9YRRHfx2+FAQKNDGrssXehqLpxmwRv2mC/5ntj4=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@ -269,8 +269,8 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
@ -358,8 +358,8 @@ github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwp
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -645,7 +645,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -928,8 +927,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=
honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs=
honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=