vivarium 0.5.2 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 332c9bfd2267f44bac72dea2cf344bd5c515613333f18a479f830d72c0133749
4
- data.tar.gz: af42fd7731c9c211fd34b120125793214d485c0567310e4b3d70866eaafcbf3f
3
+ metadata.gz: 00bd1e28a68f907293bb6bd0d23ceb26443fe603e653a18a8a88a4a36575b540
4
+ data.tar.gz: 440caf222aa2003056ff827b8da3a211da1ea3fc25aae1c237b433d040331abb
5
5
  SHA512:
6
- metadata.gz: f3543e2ee6a9b03a9916fb501957779b543782b8e247d66f084dddbd1372bfcc4de91082d7c875b25d7ff12fc9ad905c8675387df8eb049e40b2e57db121ff18
7
- data.tar.gz: 604698d87ca591abdab4ead63bfd0053c43c9e5caaf86524eca626561a5e4e8bc47f267546ad4ac6882dd1f5f6692acf77eabf1e545aae0bba73b73daebf7033
6
+ metadata.gz: 7120d43057fa8f532c6fcffd512d33b5392bd7fe7cf174811afd3fc737c515230b6e82cad2ea26b776b129817a350467f4b5beb007dcf009c58c2b6cf656227c
7
+ data.tar.gz: 2502ea29816994a2a8dfa05c65c9302da57f74b29790692111e23c5afdd093ba7e2c992b84ab218234cd3e9701df08ea885549023264c6a92868fc882a72c18f
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "fiddle"
5
+ require "vivarium"
6
+
7
+ FILTER = {
8
+ include_events: %w[dlopen mmap_exec]
9
+ }.freeze
10
+
11
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
12
+
13
+ # Usage:
14
+ # 1) In another shell (root): sudo bundle exec vivariumd
15
+ # (dlopen uprobe is attached automatically when libc is found)
16
+ # 2) Run this script: bundle exec ruby examples/dlopen_demo_otel.rb
17
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/dlopen_demo_otel.rb
18
+ #
19
+ # You can disable the dlopen uprobe with `sudo vivariumd --no-dlopen-trace`
20
+ # or point at a specific libc with `sudo vivariumd --libc /lib/x86_64-linux-gnu/libc.so.6`.
21
+
22
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
23
+ begin
24
+ libm = Fiddle.dlopen("libm.so.6")
25
+ sin_fn = Fiddle::Function.new(libm["sin"], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE)
26
+ puts "[dlopen_demo] sin(PI/4) = #{sin_fn.call(Math::PI / 4).round(6)}"
27
+ libm.close
28
+ rescue Fiddle::DLError => e
29
+ warn "[dlopen_demo] libm: #{e.message}"
30
+ end
31
+
32
+ begin
33
+ libsqlite3 = Fiddle.dlopen("libsqlite3.so.0")
34
+ puts "[dlopen_demo] libsqlite3 loaded: version = #{Fiddle::Function.new(libsqlite3["sqlite3_libversion"], [], Fiddle::TYPE_VOIDP).call}"
35
+ libsqlite3.close
36
+ rescue Fiddle::DLError => e
37
+ warn "[dlopen_demo] libsqlite3: #{e.message}"
38
+ end
39
+
40
+ Bundler.with_unbundled_env do
41
+ system("ruby -e 'require \"fiddle\"; Fiddle.dlopen(\"libm.so.6\").close'")
42
+ end
43
+ end
44
+
45
+ puts "[dlopen_demo] done"
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "rbconfig"
5
+ require "vivarium"
6
+
7
+ FILTER = {
8
+ include_events: %w[env_caccess proc_fork proc_exec]
9
+ }.freeze
10
+
11
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
12
+
13
+ # Usage:
14
+ # 1) In another shell (root): sudo bundle exec vivariumd
15
+ # 2) Run this script: bundle exec ruby examples/env_access_external_demo_otel.rb
16
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/env_access_external_demo_otel.rb
17
+ #
18
+ # This demo launches an external Ruby process and forces direct libc calls to
19
+ # getenv/setenv/unsetenv/putenv/clearenv through Fiddle.
20
+
21
+ CHILD_CODE = <<~RUBY
22
+ require "fiddle"
23
+
24
+ libc = begin
25
+ Fiddle.dlopen("libc.so.6")
26
+ rescue Fiddle::DLError
27
+ Fiddle.dlopen(nil)
28
+ end
29
+
30
+ getenv = Fiddle::Function.new(libc["getenv"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
31
+ setenv = Fiddle::Function.new(libc["setenv"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT], Fiddle::TYPE_INT)
32
+ unsetenv = Fiddle::Function.new(libc["unsetenv"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
33
+ putenv = Fiddle::Function.new(libc["putenv"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
34
+ clearenv = Fiddle::Function.new(libc["clearenv"], [], Fiddle::TYPE_INT)
35
+
36
+ key = "VIVARIUM_ENV_EXT_DEMO"
37
+ putenv_buf = "VIVARIUM_ENV_EXT_PUT=from_putenv"
38
+
39
+ getenv.call("HOME")
40
+ setenv.call(key, "from_setenv", 1)
41
+ getenv.call(key)
42
+ putenv.call(putenv_buf)
43
+ unsetenv.call(key)
44
+ clearenv.call
45
+ RUBY
46
+
47
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
48
+ puts "[env-external-demo] spawning external child"
49
+ pid = Process.spawn(RbConfig.ruby, "-e", CHILD_CODE)
50
+ Process.wait(pid)
51
+ puts "[env-external-demo] child exit status=#{Process.last_status.exitstatus}"
52
+ end
53
+
54
+ puts "[env-external-demo] done"
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "vivarium"
5
+
6
+ FILTER = {
7
+ include_events: %w[span_start span_stop env_caccess]
8
+ }.freeze
9
+
10
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
11
+
12
+ # Usage:
13
+ # 1) In another shell (root): sudo bundle exec vivariumd
14
+ # 2) Run this script: bundle exec ruby examples/env_access_ruby_demo_otel.rb
15
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/env_access_ruby_demo_otel.rb
16
+
17
+ def safe_fetch(key)
18
+ ENV.fetch(key)
19
+ rescue KeyError
20
+ nil
21
+ end
22
+
23
+ def demo_env_reads
24
+ ENV["HOME"]
25
+ safe_fetch("PATH")
26
+ ENV.key?("SHELL")
27
+ end
28
+
29
+ def demo_env_writes
30
+ ENV["VIVARIUM_ENV_DEMO_A"] = "1"
31
+ ENV.store("VIVARIUM_ENV_DEMO_B", "2")
32
+ ENV.delete("VIVARIUM_ENV_DEMO_A")
33
+ ENV.replace(ENV.to_h.merge("VIVARIUM_ENV_DEMO_C" => "3"))
34
+ ENV.delete("VIVARIUM_ENV_DEMO_B")
35
+ ENV.delete("VIVARIUM_ENV_DEMO_C")
36
+ end
37
+
38
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
39
+ original_env = ENV.to_h
40
+
41
+ puts "[env-ruby-demo] read methods"
42
+ demo_env_reads
43
+
44
+ puts "[env-ruby-demo] write methods"
45
+ demo_env_writes
46
+
47
+ puts "[env-ruby-demo] clear"
48
+ ENV.clear
49
+ ENV.replace(original_env)
50
+ end
51
+
52
+ puts "[env-ruby-demo] done"
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "tmpdir"
5
+ require "vivarium"
6
+
7
+ TMP_PREFIX = "vivarium-exec-demo"
8
+ FILTER = {
9
+ include_events: %w[proc_exec]
10
+ }.freeze
11
+
12
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
13
+
14
+ # Usage:
15
+ # 1) In another shell (root): sudo bundle exec vivariumd
16
+ # 2) Run this script: bundle exec ruby examples/execve_demo_otel.rb
17
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/execve_demo_otel.rb
18
+
19
+ def try_step(title)
20
+ puts "[exec-demo] #{title}"
21
+ yield
22
+ rescue StandardError => e
23
+ puts "[exec-demo] #{title} failed: #{e.class}: #{e.message}"
24
+ end
25
+
26
+ Dir.mktmpdir(TMP_PREFIX, "/tmp") do |dir|
27
+ output_path = File.join(dir, "execve-demo.out")
28
+
29
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
30
+ try_step("system echo with multiple args") do
31
+ system("/bin/echo", "hello", "from", "vivarium", out: File::NULL)
32
+ end
33
+
34
+ try_step("spawn env with explicit argv") do
35
+ pid = Process.spawn(
36
+ "/usr/bin/env",
37
+ "env",
38
+ "printf",
39
+ "execve-demo\n",
40
+ out: output_path,
41
+ err: File::NULL
42
+ )
43
+ Process.wait(pid)
44
+ end
45
+
46
+ try_step("spawn sleep with flag") do
47
+ pid = Process.spawn("/bin/sleep", "0")
48
+ Process.wait(pid)
49
+ end
50
+ end
51
+
52
+ puts "[exec-demo] output file: #{output_path}" if File.exist?(output_path)
53
+ end
54
+
55
+ puts "[exec-demo] done"
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "fileutils"
5
+ require "tmpdir"
6
+ require "vivarium"
7
+
8
+ TMP_PREFIX = "vivarium-file-demo"
9
+ FILTER = {
10
+ include_events: %w[path_open file_symlink file_hardlink file_rename file_chmod file_unlink file_getdents]
11
+ }.freeze
12
+
13
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
14
+
15
+ # Usage:
16
+ # 1) In another shell (root): sudo bundle exec vivariumd
17
+ # 2) Run this script: bundle exec ruby examples/file_operation_demo_otel.rb
18
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/file_operation_demo_otel.rb
19
+
20
+ def try_step(title)
21
+ puts "[file-demo] #{title}"
22
+ yield
23
+ rescue StandardError => e
24
+ puts "[file-demo] #{title} failed: #{e.class}: #{e.message}"
25
+ end
26
+
27
+ Dir.mktmpdir(TMP_PREFIX, "/tmp") do |dir|
28
+ source_path = File.join(dir, "source.txt")
29
+ renamed_path = File.join(dir, "renamed.txt")
30
+ hardlink_path = File.join(dir, "hardlink.txt")
31
+ symlink_path = File.join(dir, "symlink.txt")
32
+
33
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
34
+ try_step("create source file") do
35
+ File.write(source_path, "vivarium sample\n")
36
+ File.read(source_path)
37
+ end
38
+
39
+ try_step("directory listing") do
40
+ Dir.children(dir)
41
+ end
42
+
43
+ try_step("rename file") do
44
+ File.rename(source_path, renamed_path)
45
+ File.read(renamed_path)
46
+ end
47
+
48
+ try_step("create hardlink") do
49
+ File.link(renamed_path, hardlink_path)
50
+ File.read(hardlink_path)
51
+ end
52
+
53
+ try_step("create symlink") do
54
+ File.symlink(renamed_path, symlink_path)
55
+ File.read(symlink_path)
56
+ end
57
+
58
+ try_step("chmod file") do
59
+ File.chmod(0o640, renamed_path)
60
+ File.stat(renamed_path)
61
+ end
62
+
63
+ try_step("unlink hardlink") do
64
+ File.unlink(hardlink_path)
65
+ end
66
+
67
+ try_step("unlink symlink") do
68
+ File.unlink(symlink_path)
69
+ end
70
+
71
+ try_step("list directory again") do
72
+ Dir.children(dir)
73
+ end
74
+ end
75
+
76
+ FileUtils.rm_f(symlink_path)
77
+ FileUtils.rm_f(hardlink_path)
78
+ FileUtils.rm_f(renamed_path)
79
+ FileUtils.rm_f(source_path)
80
+ end
81
+
82
+ puts "[file-demo] done"
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "socket"
5
+ require "vivarium"
6
+
7
+ FILTER = {
8
+ include_events: %w[sock_connect dns_req odd_socket]
9
+ }.freeze
10
+
11
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
12
+
13
+ # Usage:
14
+ # 1) In another shell (root): sudo bundle exec vivariumd
15
+ # 2) Run this script: bundle exec ruby examples/network_client_demo_otel.rb
16
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/network_client_demo_otel.rb
17
+
18
+ def try_step(title)
19
+ puts "[client] #{title}"
20
+ yield
21
+ rescue StandardError => e
22
+ puts "[client] #{title} failed: #{e.class}: #{e.message}"
23
+ end
24
+
25
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
26
+ # Likely emits sock_connect and dns_req via resolver traffic.
27
+ try_step("system: DNS lookup") do
28
+ system("getent hosts example.com >/dev/null 2>&1 || true")
29
+ system("getent hosts unknown.example.com >/dev/null 2>&1 || true")
30
+ end
31
+
32
+ # Likely emits sock_connect through HTTPS connection attempts.
33
+ try_step("system: curl") do
34
+ system("curl -I https://example.com >/dev/null 2>&1 || true")
35
+ end
36
+
37
+ # ICMP example (may require CAP_NET_RAW / root depending on environment).
38
+ try_step("system: ping") do
39
+ system("ping -c 1 example.com >/dev/null 2>&1 || true")
40
+ end
41
+
42
+ # Explicit connect path.
43
+ try_step("Ruby TCP connect") do
44
+ sock = TCPSocket.new("example.com", 80)
45
+ sock.close
46
+ end
47
+
48
+ # Raw DNS query payload, useful for dns_req decode testing.
49
+ try_step("Ruby UDP DNS query") do
50
+ dns_query = "\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +
51
+ "\x09udp-query\x07example\x03com\x00" +
52
+ "\x00\x01\x00\x01"
53
+
54
+ udp = UDPSocket.new
55
+ begin
56
+ udp.connect("127.0.0.53", 53)
57
+ rescue StandardError
58
+ udp.connect("8.8.8.8", 53)
59
+ end
60
+ udp.send(dns_query, 0)
61
+ udp.close
62
+ end
63
+
64
+ # Explicit sendto path for DNS payload visibility.
65
+ try_step("Ruby UDP sendto DNS query") do
66
+ dns_query = "\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +
67
+ "\x06sendto\x07example\x03com\x00" +
68
+ "\x00\x01\x00\x01"
69
+
70
+ udp = UDPSocket.new
71
+ udp.send(dns_query, 0, "127.0.0.53", 53)
72
+ udp.close
73
+ end
74
+
75
+ # Intentionally unusual socket type to trigger odd_socket.
76
+ try_step("Ruby odd socket attempt") do
77
+ af_packet = Socket.const_defined?(:AF_PACKET) ? Socket::AF_PACKET : 17
78
+ raw = Socket.new(af_packet, Socket::SOCK_RAW, 0)
79
+ raw.close
80
+ end
81
+ end
82
+
83
+ puts "[client] done"
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "socket"
5
+ require "vivarium"
6
+
7
+ FILTER = {
8
+ include_events: %w[sock_connect dns_req odd_socket]
9
+ }.freeze
10
+
11
+ OTEL_OUT = ENV.fetch("VIVARIUM_OTEL_OUT", "network_client_demo_otel.json")
12
+
13
+ # Usage:
14
+ # 1) In another shell (root): sudo bundle exec vivariumd
15
+ # 2) Run this script: bundle exec ruby examples/network_client_demo_otel_out.rb
16
+ # or: VIVARIUM_OTEL_OUT=/tmp/network_client_demo_otel.json bundle exec ruby examples/network_client_demo_otel_out.rb
17
+
18
+ def try_step(title)
19
+ puts "[client] #{title}"
20
+ yield
21
+ rescue StandardError => e
22
+ puts "[client] #{title} failed: #{e.class}: #{e.message}"
23
+ end
24
+
25
+ Vivarium.observe(filter: FILTER, otel_out: OTEL_OUT) do
26
+ # Likely emits sock_connect and dns_req via resolver traffic.
27
+ try_step("system: DNS lookup") do
28
+ system("getent hosts example.com >/dev/null 2>&1 || true")
29
+ system("getent hosts unknown.example.com >/dev/null 2>&1 || true")
30
+ end
31
+
32
+ # Likely emits sock_connect through HTTPS connection attempts.
33
+ try_step("system: curl") do
34
+ system("curl -I https://example.com >/dev/null 2>&1 || true")
35
+ end
36
+
37
+ # ICMP example (may require CAP_NET_RAW / root depending on environment).
38
+ try_step("system: ping") do
39
+ system("ping -c 1 example.com >/dev/null 2>&1 || true")
40
+ end
41
+
42
+ # Explicit connect path.
43
+ try_step("Ruby TCP connect") do
44
+ sock = TCPSocket.new("example.com", 80)
45
+ sock.close
46
+ end
47
+
48
+ # Raw DNS query payload, useful for dns_req decode testing.
49
+ try_step("Ruby UDP DNS query") do
50
+ dns_query = "\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +
51
+ "\x09udp-query\x07example\x03com\x00" +
52
+ "\x00\x01\x00\x01"
53
+
54
+ udp = UDPSocket.new
55
+ begin
56
+ udp.connect("127.0.0.53", 53)
57
+ rescue StandardError
58
+ udp.connect("8.8.8.8", 53)
59
+ end
60
+ udp.send(dns_query, 0)
61
+ udp.close
62
+ end
63
+
64
+ # Explicit sendto path for DNS payload visibility.
65
+ try_step("Ruby UDP sendto DNS query") do
66
+ dns_query = "\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +
67
+ "\x06sendto\x07example\x03com\x00" +
68
+ "\x00\x01\x00\x01"
69
+
70
+ udp = UDPSocket.new
71
+ udp.send(dns_query, 0, "127.0.0.53", 53)
72
+ udp.close
73
+ end
74
+
75
+ # Intentionally unusual socket type to trigger odd_socket.
76
+ try_step("Ruby odd socket attempt") do
77
+ af_packet = Socket.const_defined?(:AF_PACKET) ? Socket::AF_PACKET : 17
78
+ raw = Socket.new(af_packet, Socket::SOCK_RAW, 0)
79
+ raw.close
80
+ end
81
+ end
82
+
83
+ puts "[client] wrote OTLP JSON to #{OTEL_OUT}"
84
+ puts "[client] done"
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "vivarium"
5
+
6
+ FILTER = {
7
+ include_events: %w[setid_change capable_check bprm_creds]
8
+ }.freeze
9
+
10
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
11
+
12
+ # Usage:
13
+ # 1) In another shell (root): sudo bundle exec vivariumd
14
+ # 2) Run this script: bundle exec ruby examples/privilege_event_demo_otel.rb
15
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/privilege_event_demo_otel.rb
16
+
17
+ def try_step(title)
18
+ puts "[priv-demo] #{title}"
19
+ yield
20
+ rescue StandardError => e
21
+ puts "[priv-demo] #{title} failed: #{e.class}: #{e.message}"
22
+ end
23
+
24
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
25
+ try_step("attempt setuid(0)") do
26
+ Process::UID.change_privilege(0)
27
+ end
28
+
29
+ try_step("attempt setgid(0)") do
30
+ Process::GID.change_privilege(0)
31
+ end
32
+
33
+ try_step("attempt opening /etc/shadow") do
34
+ File.read("/etc/shadow")
35
+ end
36
+
37
+ try_step("exec setuid-related binary") do
38
+ pid = Process.spawn("/usr/bin/sudo", "-n", "true", out: File::NULL, err: File::NULL)
39
+ Process.wait(pid)
40
+ rescue Errno::ENOENT
41
+ puts "[priv-demo] sudo not found; skipped"
42
+ end
43
+ end
44
+
45
+ puts "[priv-demo] done"
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "vivarium"
5
+
6
+ FILTER = {
7
+ include_events: %w[span_raise]
8
+ }.freeze
9
+
10
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
11
+
12
+ def try_step(title)
13
+ puts "[priv-demo] #{title}"
14
+ yield
15
+ rescue StandardError => e
16
+ puts "[priv-demo] #{title} failed: #{e.class}: #{e.message}"
17
+ end
18
+
19
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
20
+ try_step("raise in main") do
21
+ raise "error in main"
22
+ end
23
+
24
+ try_step("raise in eval") do
25
+ eval("raise 'error in eval'")
26
+ end
27
+
28
+ try_step("raise in nested eval") do
29
+ eval(<<~RUBY)
30
+ eval(<<~INNER_RUBY)
31
+ begin
32
+ eval(<<~INNER_INNER_RUBY)
33
+ puts "Hi"
34
+ raise "error in nested nested eval"
35
+ INNER_INNER_RUBY
36
+ rescue StandardError => _
37
+ puts "Rescued in nested eval"
38
+ end
39
+ File.open("/etc/hosts")
40
+ INNER_RUBY
41
+ RUBY
42
+ end
43
+
44
+ try_step("raise in method") do
45
+ File.open("notfound")
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "net/http"
5
+ require "uri"
6
+ require "vivarium"
7
+
8
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
9
+
10
+ # Usage:
11
+ # 1) In another shell (root): sudo bundle exec vivariumd
12
+ # 2) Run this script: bundle exec ruby examples/save_raw_demo_otel.rb
13
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/save_raw_demo_otel.rb
14
+ #
15
+ # Note: this is the OTLP streaming variant of save_raw_demo.rb, so no vivraw file is written.
16
+
17
+ Vivarium.observe(otel_endpoint: OTEL_ENDPOINT) do
18
+ path = "/tmp/vivarium_save_raw_demo.txt"
19
+ File.write(path, "hello from save_raw demo\n")
20
+ File.chmod(0o600, path)
21
+ File.delete(path)
22
+
23
+ begin
24
+ uri = URI("https://udzura.jp/")
25
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
26
+ http.get(uri.request_uri)
27
+ end
28
+ rescue StandardError => e
29
+ warn "[save_raw_demo] Net::HTTP failed: #{e.class}: #{e.message}"
30
+ end
31
+
32
+ system("true")
33
+ end
34
+
35
+ puts "[save_raw_demo] streamed OTLP events to #{OTEL_ENDPOINT}"
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "vivarium"
5
+
6
+ FILTER = {
7
+ include_events: %w[task_kill]
8
+ }.freeze
9
+
10
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
11
+
12
+ # Usage:
13
+ # 1) In another shell (root): sudo bundle exec vivariumd
14
+ # 2) Run this script: bundle exec ruby examples/signal_kill_demo_otel.rb
15
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/signal_kill_demo_otel.rb
16
+
17
+ def try_step(title)
18
+ puts "[signal-demo] #{title}"
19
+ yield
20
+ rescue StandardError => e
21
+ puts "[signal-demo] #{title} failed: #{e.class}: #{e.message}"
22
+ end
23
+
24
+ child_pid = nil
25
+
26
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
27
+ try_step("fork child process") do
28
+ child_pid = fork do
29
+ trap("TERM") { exit!(0) }
30
+ loop { sleep 1 }
31
+ end
32
+ puts "[signal-demo] child pid=#{child_pid}"
33
+ end
34
+
35
+ try_step("send TERM signal to child") do
36
+ sleep 0.1
37
+ Process.kill("TERM", child_pid)
38
+ end
39
+
40
+ try_step("wait child process") do
41
+ Process.wait(child_pid)
42
+ end
43
+ end
44
+
45
+ puts "[signal-demo] done"
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "net/http"
5
+ require "uri"
6
+ require "vivarium"
7
+
8
+ FILTER = {
9
+ include_events: %w[ssl_write]
10
+ }.freeze
11
+
12
+ OTEL_ENDPOINT = ENV.fetch("VIVARIUM_OTEL_ENDPOINT", "http://localhost:4318/v1/traces")
13
+
14
+ # Usage:
15
+ # 1) In another shell (root): sudo bundle exec vivariumd
16
+ # (SSL_write uprobe is attached automatically when libssl is found)
17
+ # 2) Run this script: bundle exec ruby examples/ssl_write_demo_otel.rb
18
+ # or: VIVARIUM_OTEL_ENDPOINT=http://collector:4318/v1/traces bundle exec ruby examples/ssl_write_demo_otel.rb
19
+ #
20
+ # You can disable the SSL_write uprobe with `sudo vivariumd --no-ssl-trace`
21
+ # or point at a specific library with `sudo vivariumd --libssl /path/to/libssl.so.3`.
22
+
23
+ Vivarium.observe(filter: FILTER, otel_endpoint: OTEL_ENDPOINT) do
24
+ begin
25
+ uri = URI("https://udzura.jp/")
26
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
27
+ http.get(uri.request_uri)
28
+ end
29
+ rescue StandardError => e
30
+ warn "[ssl_demo] Net::HTTP failed: #{e.class}: #{e.message}"
31
+ end
32
+
33
+ system("curl -sS --http2 -o /dev/null https://nghttp2.org/ 2>/dev/null")
34
+ end
35
+
36
+ puts "[ssl_demo] done"