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 +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +5 -2
- data/README.md +9 -1
- data/Rakefile +1 -1
- data/lib/tsclient/client.rb +57 -0
- data/lib/tsclient/profile.rb +19 -0
- data/lib/tsclient/result.rb +9 -0
- data/lib/tsclient/version.rb +1 -1
- data/lib/tsclient.rb +21 -1
- data/tsclient.gemspec +3 -0
- metadata +32 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2a91d5b540777dd21e95c45f79ae5b629f88dfeb5b145a896eff8de50db605e
|
|
4
|
+
data.tar.gz: c9432bed5af0ec0d1326f95ebf2a3c8867e348ae8ee628a96bd321cd5224640a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -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
|
data/lib/tsclient/version.rb
CHANGED
data/lib/tsclient.rb
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "tsclient/
|
|
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
|
|
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
|