ddtrace 1.10.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -2
- data/LICENSE-3rdparty.csv +1 -0
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +3 -10
- data/lib/datadog/ci/ext/environment.rb +2 -20
- data/lib/datadog/core/configuration/components.rb +1 -1
- data/lib/datadog/core/utils/network.rb +140 -0
- data/lib/datadog/core/vendor/ipaddr.rb +78 -0
- data/lib/datadog/kit/appsec/events.rb +1 -1
- data/lib/datadog/tracing/client_ip.rb +39 -140
- data/lib/ddtrace/transport/http/traces.rb +1 -1
- data/lib/ddtrace/transport/traces.rb +1 -1
- data/lib/ddtrace/version.rb +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 005fcbaaa9553287f8652a9f437abd144c2ba2ca0f26c83f67de171646f5aae3
|
|
4
|
+
data.tar.gz: 032c0d3f09ea01779b17ba45a95086ab890b3869208c84b82b548b3cbd41a977
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bc868d2e56e5282771cbc7e9447f1fa7504212d31b5bc94db4db9e5f029a00b0a9f988bcab7111f1889eb1f203fffcd81b73700c69f433be4bdaa2045dbfba72
|
|
7
|
+
data.tar.gz: d2679f725e7991bfa2e34dc6de650e928a59aa02124239d340a396ea40f331ff0a4a2159067df5ade22c1c36daab8e7cbe25db3ddaf55b8c8cb14137e7b2d220
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.10.1] - 2023-03-10
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
* CI: Update TeamCity environment variable support ([#2668][])
|
|
10
|
+
* Core: Fix spurious dependency on AppSec when loading CI with `require 'datadog/ci'` ([#2679][])
|
|
11
|
+
* Core: Allow multiple headers and multiple IPs per header for client IP ([#2665][])
|
|
12
|
+
* AppSec: prevent side-effect on AppSec login event tracking method arguments ([#2663][]) ([@coneill-enhance][])
|
|
13
|
+
|
|
5
14
|
## [1.10.0] - 2023-03-06
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -2314,7 +2323,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
|
|
|
2314
2323
|
|
|
2315
2324
|
Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
2316
2325
|
|
|
2317
|
-
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.
|
|
2326
|
+
[Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.1...master
|
|
2327
|
+
[1.10.1]: https://github.com/DataDog/dd-trace-rb/compare/v1.10.0...v1.10.1
|
|
2318
2328
|
[1.10.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.9.0...v1.10.0
|
|
2319
2329
|
[1.9.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.8.0...v1.9.0
|
|
2320
2330
|
[1.8.0]: https://github.com/DataDog/dd-trace-rb/compare/v1.7.0...v1.8.0
|
|
@@ -3321,6 +3331,10 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
3321
3331
|
[#2657]: https://github.com/DataDog/dd-trace-rb/issues/2657
|
|
3322
3332
|
[#2659]: https://github.com/DataDog/dd-trace-rb/issues/2659
|
|
3323
3333
|
[#2662]: https://github.com/DataDog/dd-trace-rb/issues/2662
|
|
3334
|
+
[#2663]: https://github.com/DataDog/dd-trace-rb/issues/2663
|
|
3335
|
+
[#2665]: https://github.com/DataDog/dd-trace-rb/issues/2665
|
|
3336
|
+
[#2668]: https://github.com/DataDog/dd-trace-rb/issues/2668
|
|
3337
|
+
[#2679]: https://github.com/DataDog/dd-trace-rb/issues/2679
|
|
3324
3338
|
[@AdrianLC]: https://github.com/AdrianLC
|
|
3325
3339
|
[@Azure7111]: https://github.com/Azure7111
|
|
3326
3340
|
[@BabyGroot]: https://github.com/BabyGroot
|
|
@@ -3365,6 +3379,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
3365
3379
|
[@cjford]: https://github.com/cjford
|
|
3366
3380
|
[@ck3g]: https://github.com/ck3g
|
|
3367
3381
|
[@components]: https://github.com/components
|
|
3382
|
+
[@coneill-enhance]: https://github.com/coneill-enhance
|
|
3368
3383
|
[@cswatt]: https://github.com/cswatt
|
|
3369
3384
|
[@cwoodcox]: https://github.com/cwoodcox
|
|
3370
3385
|
[@danhodge]: https://github.com/danhodge
|
|
@@ -3466,4 +3481,4 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
|
|
|
3466
3481
|
[@y-yagi]: https://github.com/y-yagi
|
|
3467
3482
|
[@yujideveloper]: https://github.com/yujideveloper
|
|
3468
3483
|
[@yukimurasawa]: https://github.com/yukimurasawa
|
|
3469
|
-
[@zachmccormick]: https://github.com/zachmccormick
|
|
3484
|
+
[@zachmccormick]: https://github.com/zachmccormick
|
data/LICENSE-3rdparty.csv
CHANGED
|
@@ -5,3 +5,4 @@ lib/datadog/tracing/contrib/utils/quantization/http.rb,https://github.com/ruby/u
|
|
|
5
5
|
ext/ddtrace_profiling_native_extension/private_vm_api_access,https://github.com/ruby/ruby,BSD-2-Clause,"Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved."
|
|
6
6
|
msgpack,https://rubygems.org/gems/msgpack,Apache-2.0,"Copyright (c) 2008-2015 Sadayuki Furuhashi"
|
|
7
7
|
debase-ruby_core_source,https://rubygems.org/gems/debase-ruby_core_source,MIT for gem and BSD-2-Clause for Ruby sources,"Copyright (c) 2012 Gabriel Horner. Files from Ruby sources are Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved."
|
|
8
|
+
lib/datadog/core/vendor/ipaddr,https://github.com/ruby/ipaddr/blob/master/lib/ipaddr.rb,BSD 2-Clause "Simplified" License,"Copyright (c) 2002 Hajimu UMEMOTO <ume@mahoroba.org> Copyright (c) 2007-2017 Akinori MUSHA <knu@iDaemons.org>"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../../../instrumentation/gateway/argument'
|
|
4
|
+
require_relative '../../../../core/header_collection'
|
|
4
5
|
require_relative '../../../../tracing/client_ip'
|
|
5
|
-
require_relative '../../../../tracing/contrib/rack/header_collection'
|
|
6
6
|
|
|
7
7
|
module Datadog
|
|
8
8
|
module AppSec
|
|
@@ -85,16 +85,9 @@ module Datadog
|
|
|
85
85
|
|
|
86
86
|
def client_ip
|
|
87
87
|
remote_ip = remote_addr
|
|
88
|
-
|
|
88
|
+
header_collection = Datadog::Core::HeaderCollection.from_hash(headers)
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if result.raw_ip
|
|
93
|
-
ip = Datadog::Tracing::ClientIp.strip_decorations(result.raw_ip)
|
|
94
|
-
return unless Datadog::Tracing::ClientIp.valid_ip?(ip)
|
|
95
|
-
|
|
96
|
-
ip
|
|
97
|
-
end
|
|
90
|
+
Datadog::Tracing::ClientIp.extract_client_ip(header_collection, remote_ip)
|
|
98
91
|
end
|
|
99
92
|
end
|
|
100
93
|
end
|
|
@@ -174,9 +174,6 @@ module Datadog
|
|
|
174
174
|
TAG_PIPELINE_URL => url,
|
|
175
175
|
TAG_PROVIDER_NAME => 'bitbucket',
|
|
176
176
|
TAG_WORKSPACE_PATH => env['BITBUCKET_CLONE_DIR'],
|
|
177
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['BUILD_REQUESTEDFORID'],
|
|
178
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['BUILD_REQUESTEDFOREMAIL'],
|
|
179
|
-
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BUILD_SOURCEVERSIONMESSAGE']
|
|
180
177
|
}
|
|
181
178
|
end
|
|
182
179
|
|
|
@@ -265,9 +262,6 @@ module Datadog
|
|
|
265
262
|
TAG_PIPELINE_URL => pipeline_url,
|
|
266
263
|
TAG_PROVIDER_NAME => 'github',
|
|
267
264
|
TAG_WORKSPACE_PATH => env['GITHUB_WORKSPACE'],
|
|
268
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['BUILD_REQUESTEDFORID'],
|
|
269
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['BUILD_REQUESTEDFOREMAIL'],
|
|
270
|
-
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BUILD_SOURCEVERSIONMESSAGE'],
|
|
271
265
|
TAG_CI_ENV_VARS => {
|
|
272
266
|
'GITHUB_SERVER_URL' => env['GITHUB_SERVER_URL'],
|
|
273
267
|
'GITHUB_REPOSITORY' => env['GITHUB_REPOSITORY'],
|
|
@@ -325,9 +319,6 @@ module Datadog
|
|
|
325
319
|
TAG_PIPELINE_URL => env['BUILD_URL'],
|
|
326
320
|
TAG_PROVIDER_NAME => 'jenkins',
|
|
327
321
|
TAG_WORKSPACE_PATH => env['WORKSPACE'],
|
|
328
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['BUILD_REQUESTEDFORID'],
|
|
329
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['BUILD_REQUESTEDFOREMAIL'],
|
|
330
|
-
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BUILD_SOURCEVERSIONMESSAGE'],
|
|
331
322
|
TAG_CI_ENV_VARS => {
|
|
332
323
|
'DD_CUSTOM_TRACE_ID' => env['DD_CUSTOM_TRACE_ID']
|
|
333
324
|
}.to_json
|
|
@@ -337,17 +328,8 @@ module Datadog
|
|
|
337
328
|
def extract_teamcity(env)
|
|
338
329
|
{
|
|
339
330
|
TAG_PROVIDER_NAME => 'teamcity',
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
TAG_WORKSPACE_PATH => env['BUILD_CHECKOUTDIR'],
|
|
343
|
-
TAG_PIPELINE_ID => env['BUILD_ID'],
|
|
344
|
-
TAG_PIPELINE_NUMBER => env['BUILD_NUMBER'],
|
|
345
|
-
TAG_PIPELINE_URL => (
|
|
346
|
-
env['SERVER_URL'] && env['BUILD_ID'] ? "#{env['SERVER_URL']}/viewLog.html?buildId=#{env['BUILD_ID']}" : nil
|
|
347
|
-
),
|
|
348
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['BUILD_REQUESTEDFORID'],
|
|
349
|
-
Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['BUILD_REQUESTEDFOREMAIL'],
|
|
350
|
-
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BUILD_SOURCEVERSIONMESSAGE']
|
|
331
|
+
TAG_JOB_NAME => env['TEAMCITY_BUILDCONF_NAME'],
|
|
332
|
+
TAG_JOB_URL => env['BUILD_URL'],
|
|
351
333
|
}
|
|
352
334
|
end
|
|
353
335
|
|
|
@@ -88,7 +88,7 @@ module Datadog
|
|
|
88
88
|
@telemetry = self.class.build_telemetry(settings)
|
|
89
89
|
|
|
90
90
|
# AppSec
|
|
91
|
-
@appsec = Datadog::AppSec::Component.build_appsec_component(settings
|
|
91
|
+
@appsec = Datadog::AppSec::Component.build_appsec_component(settings)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# Starts up components
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ipaddr'
|
|
4
|
+
require_relative '../vendor/ipaddr'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Core
|
|
8
|
+
module Utils
|
|
9
|
+
# Common Network utility functions.
|
|
10
|
+
module Network
|
|
11
|
+
DEFAULT_IP_HEADERS_NAMES = %w[
|
|
12
|
+
x-forwarded-for
|
|
13
|
+
x-real-ip
|
|
14
|
+
true-client-ip
|
|
15
|
+
x-client-ip
|
|
16
|
+
x-forwarded
|
|
17
|
+
forwarded-for
|
|
18
|
+
x-cluster-client-ip
|
|
19
|
+
fastly-client-ip
|
|
20
|
+
cf-connecting-ip
|
|
21
|
+
cf-connecting-ipv6
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
# Returns a client IP associated with the request if it was
|
|
26
|
+
# retrieved successfully.
|
|
27
|
+
#
|
|
28
|
+
#
|
|
29
|
+
# @param [Datadog::Core::HeaderCollection, #get, nil] headers The request headers
|
|
30
|
+
# @param [Array<String>] list of headers to check.
|
|
31
|
+
# @return [String] IP value without the port and the zone indentifier.
|
|
32
|
+
# @return [nil] when no valid IP value found.
|
|
33
|
+
def stripped_ip_from_request_headers(headers, ip_headers_to_check: DEFAULT_IP_HEADERS_NAMES)
|
|
34
|
+
ip = ip_header(headers, ip_headers_to_check)
|
|
35
|
+
|
|
36
|
+
ip ? ip.to_s : nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param [String] IP value.
|
|
40
|
+
# @return [String] IP value without the port and the zone indentifier.
|
|
41
|
+
# @return [nil] when no valid IP value found.
|
|
42
|
+
def stripped_ip(ip)
|
|
43
|
+
ip = ip_to_ipaddr(ip)
|
|
44
|
+
ip ? ip.to_s : nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# @param [String] IP value.
|
|
50
|
+
# @return [IPaddr]
|
|
51
|
+
# @return [nil] when no valid IP value found.
|
|
52
|
+
def ip_to_ipaddr(ip)
|
|
53
|
+
return unless ip
|
|
54
|
+
|
|
55
|
+
clean_ip = if likely_ipv4?(ip)
|
|
56
|
+
strip_ipv4_port(ip)
|
|
57
|
+
else
|
|
58
|
+
strip_zone_specifier(strip_ipv6_port(ip))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
begin
|
|
62
|
+
IPAddr.new(clean_ip)
|
|
63
|
+
rescue IPAddr::Error
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def ip_header(headers, ip_headers_to_check)
|
|
69
|
+
return unless headers
|
|
70
|
+
|
|
71
|
+
ip_headers_to_check.each do |name|
|
|
72
|
+
value = headers.get(name)
|
|
73
|
+
|
|
74
|
+
next unless value
|
|
75
|
+
|
|
76
|
+
ips = value.split(',')
|
|
77
|
+
ips.each do |ip|
|
|
78
|
+
parsed_ip = ip_to_ipaddr(ip.strip)
|
|
79
|
+
|
|
80
|
+
return parsed_ip if global_ip?(parsed_ip)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns whether the given value is more likely to be an IPv4 than an IPv6 address.
|
|
88
|
+
#
|
|
89
|
+
# This is done by checking if a dot (`'.'`) character appears before a colon (`':'`) in the value.
|
|
90
|
+
# The rationale is that in valid IPv6 addresses, colons will always preced dots,
|
|
91
|
+
# and in valid IPv4 addresses dots will always preced colons.
|
|
92
|
+
def likely_ipv4?(value)
|
|
93
|
+
dot_index = value.index('.') || value.size
|
|
94
|
+
colon_index = value.index(':') || value.size
|
|
95
|
+
|
|
96
|
+
dot_index < colon_index
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def strip_zone_specifier(ipv6)
|
|
100
|
+
ipv6.gsub(/%.*/, '')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def strip_ipv6_port(ip)
|
|
104
|
+
if /\[(.*)\](?::\d+)?/ =~ ip
|
|
105
|
+
Regexp.last_match(1)
|
|
106
|
+
else
|
|
107
|
+
ip
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def strip_ipv4_port(ip)
|
|
112
|
+
ip.gsub(/:\d+\z/, '')
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def global_ip?(parsed_ip)
|
|
116
|
+
parsed_ip && !private?(parsed_ip) && !loopback?(parsed_ip) && !link_local?(parsed_ip)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# TODO: remove once we drop support for ruby 2.1, 2.2, 2.3, 2.4
|
|
120
|
+
# replace with ip.private?
|
|
121
|
+
def private?(ip)
|
|
122
|
+
Datadog::Core::Vendor::IPAddr.private?(ip)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# TODO: remove once we drop support for ruby 2.1, 2.2, 2.3, 2.4
|
|
126
|
+
# replace with ip.link_local?
|
|
127
|
+
def link_local?(ip)
|
|
128
|
+
Datadog::Core::Vendor::IPAddr.link_local?(ip)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# TODO: remove once we drop support for ruby 2.1, 2.2, 2.3, 2.4
|
|
132
|
+
# replace with ip.loopback
|
|
133
|
+
def loopback?(ip)
|
|
134
|
+
Datadog::Core::Vendor::IPAddr.loopback?(ip)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Copyright (c) 2002 Hajimu UMEMOTO <ume@mahoroba.org>
|
|
2
|
+
# Copyright (c) 2007-2017 Akinori MUSHA <knu@iDaemons.org>
|
|
3
|
+
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions
|
|
6
|
+
# are met:
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright
|
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
|
9
|
+
# 2. Redistributions in binary form must reproduce the above copyright
|
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
14
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
15
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
16
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
17
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
18
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
19
|
+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
20
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
21
|
+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
22
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
23
|
+
# SUCH DAMAGE.
|
|
24
|
+
|
|
25
|
+
module Datadog
|
|
26
|
+
module Core
|
|
27
|
+
module Vendor
|
|
28
|
+
# vendor code from https://github.com/ruby/ipaddr/blob/master/lib/ipaddr.rb
|
|
29
|
+
# Ruby version below 2.5 does not have the IpAddr#private? method
|
|
30
|
+
# We have to vendor the code because ruby versions below 2.5 did not extract ipaddr as a gem
|
|
31
|
+
# So we can not specify a specific version for ipaddr for ruby versions: 2.1, 2.2, 2.3, 2.4
|
|
32
|
+
module IPAddr
|
|
33
|
+
class << self
|
|
34
|
+
def private?(ip)
|
|
35
|
+
addr = ip.instance_variable_get(:@addr)
|
|
36
|
+
|
|
37
|
+
case ip.family
|
|
38
|
+
when Socket::AF_INET
|
|
39
|
+
addr & 0xff000000 == 0x0a000000 || # 10.0.0.0/8
|
|
40
|
+
addr & 0xfff00000 == 0xac100000 || # 172.16.0.0/12
|
|
41
|
+
addr & 0xffff0000 == 0xc0a80000 # 192.168.0.0/16
|
|
42
|
+
when Socket::AF_INET6
|
|
43
|
+
addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000
|
|
44
|
+
else
|
|
45
|
+
raise ::IPAddr::AddressFamilyError, 'unsupported address family'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def link_local?(ip)
|
|
50
|
+
addr = ip.instance_variable_get(:@addr)
|
|
51
|
+
|
|
52
|
+
case ip.family
|
|
53
|
+
when Socket::AF_INET
|
|
54
|
+
addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16
|
|
55
|
+
when Socket::AF_INET6
|
|
56
|
+
addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000
|
|
57
|
+
else
|
|
58
|
+
raise ::IPAddr::AddressFamilyError, 'unsupported address family'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def loopback?(ip)
|
|
63
|
+
addr = ip.instance_variable_get(:@addr)
|
|
64
|
+
|
|
65
|
+
case ip.family
|
|
66
|
+
when Socket::AF_INET
|
|
67
|
+
addr & 0xff000000 == 0x7f000000
|
|
68
|
+
when Socket::AF_INET6
|
|
69
|
+
addr == 1
|
|
70
|
+
else
|
|
71
|
+
raise ::IPAddr::AddressFamilyError, 'unsupported address family'
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -1,162 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative '../core/configuration'
|
|
4
|
+
require_relative '../core/utils/network'
|
|
2
5
|
require_relative 'metadata/ext'
|
|
3
6
|
require_relative 'span'
|
|
4
7
|
|
|
5
|
-
require 'ipaddr'
|
|
6
|
-
|
|
7
8
|
module Datadog
|
|
8
9
|
module Tracing
|
|
9
10
|
# Common functions for supporting the `http.client_ip` span attribute.
|
|
10
11
|
module ClientIp
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Sets the `http.client_ip` tag on the given span.
|
|
26
|
-
#
|
|
27
|
-
# This function respects the user's settings: if they disable the client IP tagging,
|
|
28
|
-
# or provide a different IP header name.
|
|
29
|
-
#
|
|
30
|
-
# If multiple IP headers are present in the request, this function will instead set
|
|
31
|
-
# the `_dd.multiple-ip-headers` tag with the names of the present headers,
|
|
32
|
-
# and **NOT** set the `http.client_ip` tag.
|
|
33
|
-
#
|
|
34
|
-
# @param [Span] span The span that's associated with the request.
|
|
35
|
-
# @param [HeaderCollection, #get, nil] headers A collection with the request headers.
|
|
36
|
-
# @param [String, nil] remote_ip The remote IP the request associated with the span is sent to.
|
|
37
|
-
def self.set_client_ip_tag(span, headers: nil, remote_ip: nil)
|
|
38
|
-
return unless configuration.enabled
|
|
39
|
-
|
|
40
|
-
set_client_ip_tag!(span, headers: headers, remote_ip: remote_ip)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Forcefully sets the `http.client_ip` tag on the given span.
|
|
44
|
-
#
|
|
45
|
-
# This function ignores the user's `enabled` setting.
|
|
46
|
-
#
|
|
47
|
-
# @param [Span] span The span that's associated with the request.
|
|
48
|
-
# @param [HeaderCollection, #get, nil] headers A collection with the request headers.
|
|
49
|
-
# @param [String, nil] remote_ip The remote IP the request associated with the span is sent to.
|
|
50
|
-
def self.set_client_ip_tag!(span, headers: nil, remote_ip: nil)
|
|
51
|
-
result = raw_ip_from_request(headers, remote_ip)
|
|
52
|
-
|
|
53
|
-
if result.raw_ip
|
|
54
|
-
ip = strip_decorations(result.raw_ip)
|
|
55
|
-
return unless valid_ip?(ip)
|
|
56
|
-
|
|
57
|
-
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP, ip)
|
|
58
|
-
elsif result.multiple_ip_headers
|
|
59
|
-
span.set_tag(TAG_MULTIPLE_IP_HEADERS, result.multiple_ip_headers.keys.join(','))
|
|
12
|
+
class << self
|
|
13
|
+
# Sets the `http.client_ip` tag on the given span.
|
|
14
|
+
#
|
|
15
|
+
# This function respects the user's settings: if they disable the client IP tagging,
|
|
16
|
+
# or provide a different IP header name.
|
|
17
|
+
#
|
|
18
|
+
# @param [Span] span The span that's associated with the request.
|
|
19
|
+
# @param [HeaderCollection, #get, nil] headers A collection with the request headers.
|
|
20
|
+
# @param [String, nil] remote_ip The remote IP the request associated with the span is sent to.
|
|
21
|
+
def set_client_ip_tag(span, headers: nil, remote_ip: nil)
|
|
22
|
+
return unless configuration.enabled
|
|
23
|
+
|
|
24
|
+
set_client_ip_tag!(span, headers: headers, remote_ip: remote_ip)
|
|
60
25
|
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
IpExtractionResult = Struct.new(:raw_ip, :multiple_ip_headers)
|
|
64
|
-
|
|
65
|
-
# Returns a result struct that holds the raw client IP associated with the request if it was
|
|
66
|
-
# retrieved successfully.
|
|
67
|
-
#
|
|
68
|
-
# The client IP is looked up by the following logic:
|
|
69
|
-
# * If the user has configured a header name, return that header's value.
|
|
70
|
-
# * If exactly one of the known IP headers is present, return that header's value.
|
|
71
|
-
# * If none of the known IP headers are present, return the remote IP from the request.
|
|
72
|
-
#
|
|
73
|
-
# If more than one of the known IP headers is present, the result will have a `multiple_ip_headers`
|
|
74
|
-
# field with the name of the present IP headers.
|
|
75
|
-
#
|
|
76
|
-
# @param [Datadog::Core::HeaderCollection, #get, nil] headers The request headers
|
|
77
|
-
# @param [String] remote_ip The remote IP of the request.
|
|
78
|
-
# @return [IpExtractionResult] A struct that holds the unprocessed IP value,
|
|
79
|
-
# or `nil` if it wasn't found. Additionally, the `multiple_ip_headers` fields will hold the
|
|
80
|
-
# name of known IP headers present in the request if more than one of these were found.
|
|
81
|
-
def self.raw_ip_from_request(headers, remote_ip)
|
|
82
|
-
return IpExtractionResult.new(headers && headers.get(configuration.header_name), nil) if configuration.header_name
|
|
83
26
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
27
|
+
# Forcefully sets the `http.client_ip` tag on the given span.
|
|
28
|
+
#
|
|
29
|
+
# This function ignores the user's `enabled` setting.
|
|
30
|
+
#
|
|
31
|
+
# @param [Span] span The span that's associated with the request.
|
|
32
|
+
# @param [HeaderCollection, #get, nil] headers A collection with the request headers.
|
|
33
|
+
# @param [String, nil] remote_ip The remote IP the request associated with the span is sent to.
|
|
34
|
+
def set_client_ip_tag!(span, headers: nil, remote_ip: nil)
|
|
35
|
+
ip = extract_client_ip(headers, remote_ip)
|
|
36
|
+
|
|
37
|
+
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP, ip) if ip
|
|
93
38
|
end
|
|
94
|
-
end
|
|
95
39
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
40
|
+
def extract_client_ip(headers, remote_ip)
|
|
41
|
+
if headers && configuration.header_name
|
|
42
|
+
return Datadog::Core::Utils::Network.stripped_ip_from_request_headers(
|
|
43
|
+
headers,
|
|
44
|
+
ip_headers_to_check: Array(configuration.header_name)
|
|
45
|
+
)
|
|
46
|
+
end
|
|
100
47
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
strip_zone_specifier(address)
|
|
104
|
-
end
|
|
48
|
+
ip_from_headers = Datadog::Core::Utils::Network.stripped_ip_from_request_headers(headers) if headers
|
|
105
49
|
|
|
106
|
-
|
|
107
|
-
ipv6.gsub(/%.*/, '')
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def self.strip_ipv4_port(ip)
|
|
111
|
-
ip.gsub(/:\d+\z/, '')
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def self.strip_ipv6_port(ip)
|
|
115
|
-
if /\[(.*)\](?::\d+)?/ =~ ip
|
|
116
|
-
Regexp.last_match(1)
|
|
117
|
-
else
|
|
118
|
-
ip
|
|
50
|
+
ip_from_headers || Datadog::Core::Utils::Network.stripped_ip(remote_ip)
|
|
119
51
|
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Returns whether the given value is more likely to be an IPv4 than an IPv6 address.
|
|
123
|
-
#
|
|
124
|
-
# This is done by checking if a dot (`'.'`) character appears before a colon (`':'`) in the value.
|
|
125
|
-
# The rationale is that in valid IPv6 addresses, colons will always preced dots,
|
|
126
|
-
# and in valid IPv4 addresses dots will always preced colons.
|
|
127
|
-
def self.likely_ipv4?(value)
|
|
128
|
-
dot_index = value.index('.') || value.size
|
|
129
|
-
colon_index = value.index(':') || value.size
|
|
130
|
-
|
|
131
|
-
dot_index < colon_index
|
|
132
|
-
end
|
|
133
52
|
|
|
134
|
-
|
|
135
|
-
def self.valid_ip?(ip)
|
|
136
|
-
# Client IPs should not have subnet masks even though IPAddr can parse them.
|
|
137
|
-
return false if ip.include?('/')
|
|
53
|
+
private
|
|
138
54
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
true
|
|
143
|
-
rescue IPAddr::Error
|
|
144
|
-
false
|
|
55
|
+
def configuration
|
|
56
|
+
Datadog.configuration.tracing.client_ip
|
|
145
57
|
end
|
|
146
58
|
end
|
|
147
|
-
|
|
148
|
-
def self.ip_headers(headers)
|
|
149
|
-
return {} unless headers
|
|
150
|
-
|
|
151
|
-
DEFAULT_IP_HEADERS_NAMES.each_with_object({}) do |name, result|
|
|
152
|
-
value = headers.get(name)
|
|
153
|
-
result[name] = value unless value.nil?
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def self.configuration
|
|
158
|
-
Datadog.configuration.tracing.client_ip
|
|
159
|
-
end
|
|
160
59
|
end
|
|
161
60
|
end
|
|
162
61
|
end
|
|
@@ -128,7 +128,7 @@ module Datadog
|
|
|
128
128
|
responses = chunker.encode_in_chunks(traces.lazy).map do |encoded_traces, trace_count|
|
|
129
129
|
request = Request.new(EncodedParcel.new(encoded_traces, trace_count))
|
|
130
130
|
|
|
131
|
-
client.
|
|
131
|
+
client.send_traces_payload(request).tap do |response|
|
|
132
132
|
if downgrade?(response)
|
|
133
133
|
downgrade!
|
|
134
134
|
return send_traces(traces)
|
data/lib/ddtrace/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ddtrace
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.10.
|
|
4
|
+
version: 1.10.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Datadog, Inc.
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: msgpack
|
|
@@ -281,12 +281,14 @@ files:
|
|
|
281
281
|
- lib/datadog/core/utils.rb
|
|
282
282
|
- lib/datadog/core/utils/compression.rb
|
|
283
283
|
- lib/datadog/core/utils/forking.rb
|
|
284
|
+
- lib/datadog/core/utils/network.rb
|
|
284
285
|
- lib/datadog/core/utils/object_set.rb
|
|
285
286
|
- lib/datadog/core/utils/only_once.rb
|
|
286
287
|
- lib/datadog/core/utils/safe_dup.rb
|
|
287
288
|
- lib/datadog/core/utils/sequence.rb
|
|
288
289
|
- lib/datadog/core/utils/string_table.rb
|
|
289
290
|
- lib/datadog/core/utils/time.rb
|
|
291
|
+
- lib/datadog/core/vendor/ipaddr.rb
|
|
290
292
|
- lib/datadog/core/vendor/multipart-post/LICENSE
|
|
291
293
|
- lib/datadog/core/vendor/multipart-post/multipart.rb
|
|
292
294
|
- lib/datadog/core/vendor/multipart-post/multipart/post.rb
|
|
@@ -826,7 +828,7 @@ licenses:
|
|
|
826
828
|
- BSD-3-Clause
|
|
827
829
|
metadata:
|
|
828
830
|
allowed_push_host: https://rubygems.org
|
|
829
|
-
post_install_message:
|
|
831
|
+
post_install_message:
|
|
830
832
|
rdoc_options: []
|
|
831
833
|
require_paths:
|
|
832
834
|
- lib
|
|
@@ -844,8 +846,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
844
846
|
- !ruby/object:Gem::Version
|
|
845
847
|
version: 2.0.0
|
|
846
848
|
requirements: []
|
|
847
|
-
rubygems_version: 3.3.
|
|
848
|
-
signing_key:
|
|
849
|
+
rubygems_version: 3.3.20
|
|
850
|
+
signing_key:
|
|
849
851
|
specification_version: 4
|
|
850
852
|
summary: Datadog tracing code for your Ruby applications
|
|
851
853
|
test_files: []
|