tsclient 0.0.1 → 0.1.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: c6648c361899812cae382d7837f53a701fe96ad5c88e65055d6456d9b06e89a9
4
- data.tar.gz: 58876bfffa730a35895524b3ddaae3c466f12d7577c2793d3d75b151705170ef
3
+ metadata.gz: f2a91d5b540777dd21e95c45f79ae5b629f88dfeb5b145a896eff8de50db605e
4
+ data.tar.gz: c9432bed5af0ec0d1326f95ebf2a3c8867e348ae8ee628a96bd321cd5224640a
5
5
  SHA512:
6
- metadata.gz: dc32b3da4cc1c722badaae4af2bfab56a22e3d10eff089b7c023a6fd5944b866bc8e7c772e9cfcce0aa380759be50cf3d5769592a7bcc7a3e487492fbd76674b
7
- data.tar.gz: 66205c34e15b3d97c3359da0ee87ad571830b0d87e05f1b805b813548bbb3a822625379ed4f3fd6778f18eb156ef0b701bd9e70a20ebea7c45efe4e6fcbe1607
6
+ metadata.gz: 13782f6c026d88bdf0b56cf983d9cbddd958c44b1536b22bce160f9b3090d024f7cc944b6a9b6792c8ab7366ef71a272afac5789539d57e48ac13247bda32cfd
7
+ data.tar.gz: 68cf7399a04a5e25a19a9332a9ba5bcde917f9ca1a97d58f8e729f3b78968e91ac0e211a7297aa3aa3b13696a2994c26ee1787697821e03d0e45c7d45495256d
data/CHANGELOG.md CHANGED
@@ -16,6 +16,12 @@ All notable changes to this project will be documented below. The format is base
16
16
 
17
17
  ## [Unreleased]
18
18
 
19
+ ## [0.1.0] - 2022-10-22
20
+
21
+ - Added: Client can query whois a remote address
22
+ - Added: Client can query current tailscale IPs
23
+ - Added: `Tsclient.default_client` works on macOS
24
+
19
25
  ## [0.0.1] - 2022-10-20
20
26
 
21
27
  - Added: Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tsclient (0.0.1)
4
+ tsclient (0.1.0)
5
+ json
6
+ values (~> 1.8)
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
@@ -36,9 +38,10 @@ GEM
36
38
  rubocop (= 1.35.1)
37
39
  rubocop-performance (= 1.14.3)
38
40
  unicode-display_width (2.3.0)
41
+ values (1.8.0)
39
42
 
40
43
  PLATFORMS
41
- arm64-darwin-21
44
+ ruby
42
45
 
43
46
  DEPENDENCIES
44
47
  minitest
data/README.md CHANGED
@@ -18,7 +18,15 @@ If bundler is not being used to manage dependencies, install the gem by executin
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO.
21
+ ```ruby
22
+ client = Tsclient.default_client
23
+
24
+ client.tailscale_ips
25
+ # => ["100.100.100.1", "fd7a:115c:a1e0::1"]
26
+
27
+ client.whois "100.100.100.1"
28
+ # => => #<Tsclient::Profile identifier="bob.bobbity@example.com", name="Bob Bobbity", profile_pic_url="www.google.com/images/errors/robot.png", human=true>
29
+ ```
22
30
 
23
31
  ## Development
24
32
 
data/Rakefile CHANGED
@@ -11,4 +11,4 @@ end
11
11
 
12
12
  require "standard/rake"
13
13
 
14
- task default: %i[test standard]
14
+ task default: %i[standard spec]
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "json"
5
+
6
+ require_relative "./result"
7
+ require_relative "./profile"
8
+
9
+ module Tsclient
10
+ class Client
11
+ def initialize(uri:)
12
+ @api_uri = uri.freeze
13
+ freeze
14
+ end
15
+
16
+ def tailscale_ips
17
+ api_get(:status).result.dig("TailscaleIPs")
18
+ end
19
+
20
+ def whois(addr)
21
+ unless addr.include?(":")
22
+ addr += ":80"
23
+ end
24
+ response = api_get(:whois, addr: addr)
25
+ if response.error?
26
+ nil
27
+ else
28
+ Profile.from(response.result)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def api_get(endpoint, params = {})
35
+ case @api_uri.scheme
36
+ when "http", "https"
37
+ # All we actually need is the port & password, but expect well formed URI to be passed in
38
+ Net::HTTP.start(@api_uri.host, @api_uri.port, use_ssl: (@api_uri.scheme == "https")) do |http|
39
+ req = Net::HTTP::Get.new("/localapi/v0/#{endpoint}?#{params.map { |k, v| "#{k}=#{v}" }.join("&")}")
40
+ req.basic_auth "", @api_uri.password
41
+ req.content_type = "application/json"
42
+ res = http.request(req)
43
+ case res
44
+ when Net::HTTPOK
45
+ Result.with(error: false, result: JSON.parse(res.body))
46
+ when Net::HTTPNotFound
47
+ Result.with(error: true, result: res)
48
+ end
49
+ end
50
+ when "unix"
51
+ raise NotImplemented, "unix socket not implemented"
52
+ else
53
+ raise "Can't handle api uri with scheme #{@api_uri.scheme.inspect}"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ require "values"
2
+
3
+ module Tsclient
4
+ class Profile < Value.new(:identifier, :name, :profile_pic_url, :human)
5
+ def self.from(data)
6
+ with(
7
+ identifier: data.dig("UserProfile", "LoginName"),
8
+ name: data.dig("UserProfile", "DisplayName"),
9
+ profile_pic_url: data.dig("UserProfile", "ProfilePicURL"),
10
+ # We assume anyone with an email address as their SSO identifier is human
11
+ human: data.dig("UserProfile", "LoginName").include?("@")
12
+ )
13
+ end
14
+
15
+ def human?
16
+ human
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ require "values"
2
+
3
+ module Tsclient
4
+ class Result < Value.new(:error, :result)
5
+ def error?
6
+ error
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tsclient
4
- VERSION = "0.0.1"
4
+ VERSION = "0.1.0"
5
5
  end
data/lib/tsclient.rb CHANGED
@@ -1,6 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "tsclient/version"
3
+ require_relative "tsclient/client"
4
4
 
5
5
  module Tsclient
6
+ def self.default_client
7
+ return @default_client if defined?(@default_client)
8
+
9
+ # Attempt to setup the default client from various known strategies
10
+ # Envariables override everything
11
+ uri = if ENV.key?("TS_LOCALAPI_PORT")
12
+ URI("http://:#{ENV["TS_LOCALAPI_KEY"]}@localhost:#{ENV["TS_LOCALAPI_PORT"]}")
13
+
14
+ # Running on macOS, need to find api deets from filesystem
15
+ elsif RUBY_PLATFORM["darwin"]
16
+ tsfile = Pathname.glob("#{ENV["HOME"]}/Library/Group Containers/*.io.tailscale.ipn.macos/sameuserproof-*-*").first
17
+ _, port, password = tsfile.basename.to_s.split("-", 3)
18
+ URI("http://:#{password}@localhost:#{port}")
19
+ # Throw our hands in the air, we just don't ~~care~~ know
20
+ else
21
+ raise NotImplemented, "Can't figure out where localapi is"
22
+ end
23
+
24
+ @default_client = Client.new(uri: uri)
25
+ end
6
26
  end
data/tsclient.gemspec CHANGED
@@ -31,6 +31,9 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ["lib"]
33
33
 
34
+ spec.add_dependency "json"
35
+ spec.add_dependency "values", "~> 1.8"
36
+
34
37
  spec.add_development_dependency "rake"
35
38
  spec.add_development_dependency "minitest"
36
39
  spec.add_development_dependency "standard", "~> 1.3"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tsclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caius Durling
@@ -10,6 +10,34 @@ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2022-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: values
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rake
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +96,9 @@ files:
68
96
  - README.md
69
97
  - Rakefile
70
98
  - lib/tsclient.rb
99
+ - lib/tsclient/client.rb
100
+ - lib/tsclient/profile.rb
101
+ - lib/tsclient/result.rb
71
102
  - lib/tsclient/version.rb
72
103
  - sig/tsclient.rbs
73
104
  - tsclient.gemspec