diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-26 00:10:58 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-26 00:10:58 +0300 |
commit | 098444d917f660f870daa75e9166dcb735573ad4 (patch) | |
tree | bdffb43023060a8432b4a373fb3a789d7ab7b289 /app/services/packages | |
parent | 62866a623e24242c6f7a1a93dc2aca1467d6a6ae (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/packages')
-rw-r--r-- | app/services/packages/nuget/symbols/create_symbol_files_service.rb | 20 | ||||
-rw-r--r-- | app/services/packages/nuget/symbols/extract_signature_and_checksum_service.rb (renamed from app/services/packages/nuget/symbols/extract_symbol_signature_service.rb) | 56 | ||||
-rw-r--r-- | app/services/packages/protection/delete_rule_service.rb | 43 |
3 files changed, 96 insertions, 23 deletions
diff --git a/app/services/packages/nuget/symbols/create_symbol_files_service.rb b/app/services/packages/nuget/symbols/create_symbol_files_service.rb index 03e14ba00e1..5f0b8762054 100644 --- a/app/services/packages/nuget/symbols/create_symbol_files_service.rb +++ b/app/services/packages/nuget/symbols/create_symbol_files_service.rb @@ -18,7 +18,7 @@ module Packages process_symbol_entries rescue ExtractionError => e - Gitlab::ErrorTracking.log_exception(e, class: self.class.name, package_id: package.id) + Gitlab::ErrorTracking.track_exception(e, class: self.class.name, package_id: package.id) end private @@ -31,7 +31,7 @@ module Packages raise ExtractionError, 'too many symbol entries' if index >= SYMBOL_ENTRIES_LIMIT entry.extract(tmp_file.path) { true } - File.open(tmp_file.path) do |file| + File.open(tmp_file.path, 'rb') do |file| create_symbol(entry.name, file) end end @@ -43,25 +43,27 @@ module Packages end def create_symbol(path, file) - signature = extract_signature(file.read(1.kilobyte)) - return if signature.blank? + signature, checksum = extract_signature_and_checksum(file) + return if signature.blank? || checksum.blank? ::Packages::Nuget::Symbol.create!( package: package, file: { tempfile: file, filename: path.downcase, content_type: CONTENT_TYPE }, file_path: path, signature: signature, - size: file.size + size: file.size, + file_sha256: checksum ) rescue StandardError => e - Gitlab::ErrorTracking.log_exception(e, class: self.class.name, package_id: package.id) + Gitlab::ErrorTracking.track_exception(e, class: self.class.name, package_id: package.id) end - def extract_signature(content_fragment) - ExtractSymbolSignatureService - .new(content_fragment) + def extract_signature_and_checksum(file) + ::Packages::Nuget::Symbols::ExtractSignatureAndChecksumService + .new(file) .execute .payload + .values_at(:signature, :checksum) end end end diff --git a/app/services/packages/nuget/symbols/extract_symbol_signature_service.rb b/app/services/packages/nuget/symbols/extract_signature_and_checksum_service.rb index c2ccdb517b5..fd37d139145 100644 --- a/app/services/packages/nuget/symbols/extract_symbol_signature_service.rb +++ b/app/services/packages/nuget/symbols/extract_signature_and_checksum_service.rb @@ -3,45 +3,43 @@ module Packages module Nuget module Symbols - class ExtractSymbolSignatureService + class ExtractSignatureAndChecksumService include Gitlab::Utils::StrongMemoize # More information about the GUID format can be found here: # https://github.com/dotnet/symstore/blob/main/docs/specs/SSQP_Key_Conventions.md#key-formatting-basic-rules GUID_START_INDEX = 7 - GUID_END_INDEX = 22 + GUID_END_INDEX = 26 + SIGNATURE_LENGTH = 16 + TWENTY_ZEROED_BYTES = "\u0000" * 20 GUID_PARTS_LENGTHS = [4, 2, 2, 8].freeze GUID_AGE_PART = 'FFFFFFFF' TWO_CHARACTER_HEX_REGEX = /\h{2}/ + GUID_CHUNK_SIZE = 256.bytes + SHA_CHUNK_SIZE = 16.kilobytes # The extraction of the signature in this service is based on the following documentation: # https://github.com/dotnet/symstore/blob/main/docs/specs/SSQP_Key_Conventions.md#portable-pdb-signature - def initialize(symbol_content) - @symbol_content = symbol_content + def initialize(file) + @file = file end def execute return error_response unless signature - ServiceResponse.success(payload: signature) + ServiceResponse.success(payload: { signature: signature, checksum: checksum }) end private - attr_reader :symbol_content + attr_reader :file def signature - # Find the index of the first occurrence of 'Blob' - guid_index = symbol_content.index('Blob') - return if guid_index.nil? - - # Extract the binary GUID from the symbol content - guid = symbol_content[(guid_index + GUID_START_INDEX)..(guid_index + GUID_END_INDEX)] - return if guid.nil? + return unless pdb_id # Convert the GUID into an array of two-character hex strings - guid = guid.unpack('H*').flat_map { |el| el.scan(TWO_CHARACTER_HEX_REGEX) } + guid = pdb_id.first(SIGNATURE_LENGTH).unpack('H*').flat_map { |el| el.scan(TWO_CHARACTER_HEX_REGEX) } # Reorder the GUID parts based on arbitrary lengths guid = GUID_PARTS_LENGTHS.map { |length| guid.shift(length) } @@ -54,6 +52,36 @@ module Packages end strong_memoize_attr :signature + # https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md#portable-pdb-checksum + def checksum + sha = OpenSSL::Digest.new('SHA256') + count = 0 + chunk = (+'').force_encoding(Encoding::BINARY) + file.rewind + + while file.read(SHA_CHUNK_SIZE, chunk) + count += 1 + chunk[pdb_id] = TWENTY_ZEROED_BYTES if count == 1 + sha.update(chunk) + end + + sha.hexdigest + end + + def pdb_id + # The ID is located in the first 256 bytes of the symbol `.pdb` file + chunk = file.read(GUID_CHUNK_SIZE) + return unless chunk + + # Find the index of the first occurrence of 'Blob' + guid_index = chunk.index('Blob') + return unless guid_index + + # Extract the binary GUID from the symbol content + chunk[(guid_index + GUID_START_INDEX)..(guid_index + GUID_END_INDEX)] + end + strong_memoize_attr :pdb_id + def error_response ServiceResponse.error(message: 'Could not find the signature in the symbol file') end diff --git a/app/services/packages/protection/delete_rule_service.rb b/app/services/packages/protection/delete_rule_service.rb new file mode 100644 index 00000000000..a1fa111b57b --- /dev/null +++ b/app/services/packages/protection/delete_rule_service.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Packages + module Protection + class DeleteRuleService + include Gitlab::Allowable + + def initialize(package_protection_rule, current_user:) + if package_protection_rule.blank? || current_user.blank? + raise ArgumentError, + 'package_protection_rule and current_user must be set' + end + + @package_protection_rule = package_protection_rule + @current_user = current_user + end + + def execute + unless can?(current_user, :admin_package, package_protection_rule.project) + error_message = _('Unauthorized to delete a package protection rule') + return service_response_error(message: error_message) + end + + deleted_package_protection_rule = package_protection_rule.destroy! + + ServiceResponse.success(payload: { package_protection_rule: deleted_package_protection_rule }) + rescue StandardError => e + service_response_error(message: e.message) + end + + private + + attr_reader :package_protection_rule, :current_user + + def service_response_error(message:) + ServiceResponse.error( + message: message, + payload: { package_protection_rule: nil } + ) + end + end + end +end |