ddtrace 1.10.0 → 1.10.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|