diff --git a/Steepfile b/Steepfile index 93f4974351e..27b00ccfc98 100644 --- a/Steepfile +++ b/Steepfile @@ -588,7 +588,6 @@ target :datadog do library 'ipaddr' library 'net-http' library 'securerandom' - library 'base64' library 'digest' library 'zlib' library 'time' diff --git a/datadog.gemspec b/datadog.gemspec index e036d12a22b..9002d9bda5e 100644 --- a/datadog.gemspec +++ b/datadog.gemspec @@ -60,9 +60,6 @@ Gem::Specification.new do |spec| # rubies, see #1739 and #1336 for an extended discussion about this spec.add_dependency 'msgpack' - # Requiring base64 from stdlib is deprecated in Ruby v3.3 and will be removed in v3.4 - spec.add_dependency 'base64' - # Used by the profiler native extension to support Ruby < 2.6 and > 3.2 # # We decided to pin it at the latest available version and will manually bump the dependency as needed. diff --git a/lib/datadog/appsec/event.rb b/lib/datadog/appsec/event.rb index d59d2c20cd4..7706a50de15 100644 --- a/lib/datadog/appsec/event.rb +++ b/lib/datadog/appsec/event.rb @@ -2,9 +2,9 @@ require 'json' require 'zlib' -require 'base64' require_relative 'rate_limiter' +require_relative '../core/utils/base64' module Datadog module AppSec @@ -140,7 +140,7 @@ def build_service_entry_tags(event_group) private def compressed_and_base64_encoded(value) - Base64.encode64(gzip(value)) + Datadog::Core::Utils::Base64.encode64(gzip(value)) rescue TypeError => e Datadog.logger.debug do "Failed to compress and encode value when populating AppSec::Event. Error: #{e.message}" diff --git a/lib/datadog/core/remote/client/capabilities.rb b/lib/datadog/core/remote/client/capabilities.rb index 1bb3a4c52a1..e0fe6d0f61b 100644 --- a/lib/datadog/core/remote/client/capabilities.rb +++ b/lib/datadog/core/remote/client/capabilities.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative '../../utils/base64' require_relative '../../../appsec/remote' require_relative '../../../tracing/remote' @@ -53,7 +54,7 @@ def capabilities_to_base64 cap_to_hexs = capabilities.reduce(:|).to_s(16).tap { |s| s.size.odd? && s.prepend('0') }.scan(/\h\h/) binary = cap_to_hexs.each_with_object([]) { |hex, acc| acc << hex }.map { |e| e.to_i(16) }.pack('C*') - Base64.encode64(binary).chomp + Datadog::Core::Utils::Base64.encode64(binary).chomp end end end diff --git a/lib/datadog/core/remote/transport/http/config.rb b/lib/datadog/core/remote/transport/http/config.rb index 7945acf7a95..a9e27f1eda5 100644 --- a/lib/datadog/core/remote/transport/http/config.rb +++ b/lib/datadog/core/remote/transport/http/config.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true require 'json' -require 'base64' require_relative '../config' require_relative 'client' +require_relative '../../../utils/base64' require_relative '../../../transport/http/response' require_relative '../../../transport/http/api/endpoint' @@ -51,7 +51,7 @@ def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Me # TODO: these fallbacks should be improved roots = payload[:roots] || [] - targets = payload[:targets] || Base64.encode64('{}').chomp + targets = payload[:targets] || Datadog::Core::Utils::Base64.encode64('{}').chomp target_files = payload[:target_files] || [] client_configs = payload[:client_configs] || [] @@ -61,7 +61,7 @@ def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Me raise TypeError.new(String, root) unless root.is_a?(String) decoded = begin - Base64.strict_decode64(root) # TODO: unprocessed, don't symbolize_names + Datadog::Core::Utils::Base64.strict_decode64(root) # TODO: unprocessed, don't symbolize_names rescue ArgumentError raise DecodeError.new(:roots, root) end @@ -81,7 +81,7 @@ def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Me @targets = begin decoded = begin - Base64.strict_decode64(targets) + Datadog::Core::Utils::Base64.strict_decode64(targets) rescue ArgumentError raise DecodeError.new(:targets, targets) end @@ -109,7 +109,7 @@ def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Me raise TypeError.new(String, raw) unless raw.is_a?(String) content = begin - Base64.strict_decode64(raw) + Datadog::Core::Utils::Base64.strict_decode64(raw) rescue ArgumentError raise DecodeError.new(:target_files, raw) end diff --git a/lib/datadog/core/utils/base64.rb b/lib/datadog/core/utils/base64.rb new file mode 100644 index 00000000000..1140871ee98 --- /dev/null +++ b/lib/datadog/core/utils/base64.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Datadog + module Core + module Utils + # Helper methods for encoding and decoding base64 + module Base64 + def self.encode64(bin) + [bin].pack('m') + end + + def self.strict_encode64(bin) + [bin].pack('m0') + end + + def self.strict_decode64(str) + str.unpack1('m0') + end + end + end + end +end diff --git a/sig/datadog/core/utils/base64.rbs b/sig/datadog/core/utils/base64.rbs new file mode 100644 index 00000000000..ca7d7f08ea4 --- /dev/null +++ b/sig/datadog/core/utils/base64.rbs @@ -0,0 +1,14 @@ +module Datadog + module Core + module Utils + # Helper methods for encoding and decoding base64 + module Base64 + def self.encode64: (String bin) -> String + + def self.strict_encode64: (String bin) -> String + + def self.strict_decode64: (String str) -> untyped + end + end + end +end diff --git a/spec/datadog/core/remote/client_spec.rb b/spec/datadog/core/remote/client_spec.rb index 7051621eb0f..d74ebd6c6b1 100644 --- a/spec/datadog/core/remote/client_spec.rb +++ b/spec/datadog/core/remote/client_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'spec_helper' +require 'datadog/core/utils/base64' require 'datadog/core/remote/transport/http' require 'datadog/core/remote/client' @@ -204,21 +205,21 @@ let(:rules_data_response) do { 'path' => 'datadog/603646/ASM_DD/latest/config', - 'raw' => Base64.strict_encode64(rules_data).chomp + 'raw' => Datadog::Core::Utils::Base64.strict_encode64(rules_data).chomp } end let(:blocked_ips_data_response) do { 'path' => 'datadog/603646/ASM_DATA/blocked_ips/config', - 'raw' => Base64.strict_encode64(blocked_ips).chomp + 'raw' => Datadog::Core::Utils::Base64.strict_encode64(blocked_ips).chomp } end let(:exclusion_data_response) do { 'path' => 'datadog/603646/ASM/exclusion_filters/config', - 'raw' => Base64.strict_encode64(exclusions).chomp + 'raw' => Datadog::Core::Utils::Base64.strict_encode64(exclusions).chomp } end @@ -228,8 +229,8 @@ let(:response_body) do { - 'roots' => roots.map { |r| Base64.strict_encode64(r.to_json).chomp }, - 'targets' => Base64.strict_encode64(targets.to_json).chomp, + 'roots' => roots.map { |r| Datadog::Core::Utils::Base64.strict_encode64(r.to_json).chomp }, + 'targets' => Datadog::Core::Utils::Base64.strict_encode64(targets.to_json).chomp, 'target_files' => target_files, 'client_configs' => client_configs, }.to_json @@ -380,12 +381,12 @@ context 'invalid response body' do let(:response_body) do { - 'roots' => roots.map { |r| Base64.strict_encode64(r.to_json).chomp }, - 'targets' => Base64.strict_encode64(targets.to_json).chomp, + 'roots' => roots.map { |r| Datadog::Core::Utils::Base64.strict_encode64(r.to_json).chomp }, + 'targets' => Datadog::Core::Utils::Base64.strict_encode64(targets.to_json).chomp, 'target_files' => [ { 'path' => 'datadog/603646/ASM/exclusion_filters/config', - 'raw' => Base64.strict_encode64(exclusions).chomp + 'raw' => Datadog::Core::Utils::Base64.strict_encode64(exclusions).chomp } ], 'client_configs' => [ diff --git a/spec/datadog/core/remote/transport/http_spec.rb b/spec/datadog/core/remote/transport/http_spec.rb index ef6c30dfbe2..e9b1656802f 100644 --- a/spec/datadog/core/remote/transport/http_spec.rb +++ b/spec/datadog/core/remote/transport/http_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' +require 'datadog/core/utils/base64' require 'datadog/core/remote/transport/http' require 'datadog/core/remote/transport/http/negotiation' require 'datadog/core/remote/transport/negotiation' @@ -133,7 +134,7 @@ env: Datadog.configuration.env, tags: [], }, - capabilities: Base64.encode64(capabilities_binary).chomp, + capabilities: Datadog::Core::Utils::Base64.encode64(capabilities_binary).chomp, }, cached_target_files: [], } @@ -144,11 +145,11 @@ let(:response_code) { 200 } let(:response_body) do encode = proc do |obj| - Base64.strict_encode64(obj).chomp + Datadog::Core::Utils::Base64.strict_encode64(obj).chomp end jencode = proc do |obj| - Base64.strict_encode64(JSON.dump(obj)).chomp + Datadog::Core::Utils::Base64.strict_encode64(JSON.dump(obj)).chomp end JSON.dump( diff --git a/spec/datadog/core/remote/transport/integration_spec.rb b/spec/datadog/core/remote/transport/integration_spec.rb index d8f61f3de99..a68589d6b9a 100644 --- a/spec/datadog/core/remote/transport/integration_spec.rb +++ b/spec/datadog/core/remote/transport/integration_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' +require 'datadog/core/utils/base64' require 'datadog/core/remote/transport/http' require 'datadog/core/remote/transport/http/negotiation' require 'datadog/core/remote/transport/negotiation' @@ -89,7 +90,7 @@ env: Datadog.configuration.env, tags: [], }, - capabilities: Base64.encode64(capabilities_binary).chomp, + capabilities: Datadog::Core::Utils::Base64.encode64(capabilities_binary).chomp, }, cached_target_files: [], } diff --git a/spec/datadog/tracing/contrib/suite/integration_spec.rb b/spec/datadog/tracing/contrib/suite/integration_spec.rb index 5132840e157..b6279e74baf 100644 --- a/spec/datadog/tracing/contrib/suite/integration_spec.rb +++ b/spec/datadog/tracing/contrib/suite/integration_spec.rb @@ -1,3 +1,4 @@ +require 'datadog/core/utils/base64' require 'datadog/tracing/contrib/support/spec_helper' require 'datadog' @@ -72,7 +73,7 @@ def build(*dynamic_configurations) target_files << { 'path' => target, - 'raw' => Base64.strict_encode64(raw), + 'raw' => Datadog::Core::Utils::Base64.strict_encode64(raw), } targets_targets[target] = { @@ -85,7 +86,7 @@ def build(*dynamic_configurations) { 'target_files' => target_files, - 'targets' => Base64.strict_encode64(targets.to_json), + 'targets' => Datadog::Core::Utils::Base64.strict_encode64(targets.to_json), 'client_configs' => client_configs, }.to_json end