ssh_key_switcher 1.0.3 → 1.0.5
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/README.md +24 -2
- data/lib/ssh_key_switcher/options/current_agent.rb +2 -15
- data/lib/ssh_key_switcher/options/delete.rb +3 -3
- data/lib/ssh_key_switcher/options/list.rb +32 -0
- data/lib/ssh_key_switcher/options/ping.rb +4 -1
- data/lib/ssh_key_switcher/options/remove.rb +1 -1
- data/lib/ssh_key_switcher/options/select.rb +12 -9
- data/lib/ssh_key_switcher/utils/cmd.rb +1 -5
- data/lib/ssh_key_switcher/utils/contains.rb +1 -1
- data/lib/ssh_key_switcher/utils/helper.rb +51 -10
- data/lib/ssh_key_switcher/utils/ssh_agent.rb +11 -2
- data/lib/ssh_key_switcher/version.rb +1 -1
- data/lib/ssh_key_switcher.rb +7 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2ad23e81673482e19d3eae55c0b787ef26f1dfd3f1d1e213a1c10039495478d
|
4
|
+
data.tar.gz: 1f539080d59584e814f18d4732df9e89e1c13c8607b9d5b12de6c30d536b9db4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e294cfbab8f108aa2138b780636ae58ef0686b8a62554c8d986b3d621379c56e3f03644e1a778616b727e0259e82562fa02810ad0214009f9d2dd3a84c7e45c6
|
7
|
+
data.tar.gz: 96ff45770f8fe42842fa55466e84cfd3f340bc4e14827ee120605d45b6ce6f7e96d56e26e61af3970b73cd3f6a67e024ed639058011f3407f7dba76778a9e2a2
|
data/README.md
CHANGED
@@ -64,6 +64,15 @@ $ sks -s [--select]
|
|
64
64
|
|
65
65
|
Allows you to interactively select and set an OpenSSH key for your sessions.
|
66
66
|
|
67
|
+
### List of OpenSSH Keys
|
68
|
+
|
69
|
+
```bash
|
70
|
+
$ sks -l [--list]
|
71
|
+
|
72
|
+
```
|
73
|
+
|
74
|
+
Display a list of OpenSSH keys.
|
75
|
+
|
67
76
|
### List Active OpenSSH Keys
|
68
77
|
|
69
78
|
```bash
|
@@ -92,10 +101,23 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
92
101
|
|
93
102
|
## Development
|
94
103
|
|
95
|
-
|
104
|
+
**Debug**
|
96
105
|
|
97
|
-
|
106
|
+
```bash
|
107
|
+
bundle exec sks [option]
|
108
|
+
```
|
98
109
|
|
110
|
+
**Install locally to test**
|
111
|
+
|
112
|
+
```bash
|
113
|
+
bin/install-local [version]
|
114
|
+
```
|
115
|
+
|
116
|
+
**Release**
|
117
|
+
|
118
|
+
```bash
|
119
|
+
bin/release [version]
|
120
|
+
```
|
99
121
|
|
100
122
|
## Contributor
|
101
123
|
|
@@ -5,24 +5,11 @@ module SshKeySwitcher
|
|
5
5
|
class CurrentAgent
|
6
6
|
class << self
|
7
7
|
def fetch_results
|
8
|
-
|
9
|
-
payload = Cmd.exec('ssh-add -l')[0]
|
10
|
-
payload.each_line { |line| results << line.split.last(2).join(' ') }
|
11
|
-
results
|
8
|
+
Helper.current_active_keys
|
12
9
|
end
|
13
10
|
|
14
11
|
def display
|
15
|
-
|
16
|
-
prompt.warn('No active SSH keys')
|
17
|
-
elsif fetch_results.size == 1
|
18
|
-
prompt.say('Active SSH key: ')
|
19
|
-
prompt.ok(fetch_results[0])
|
20
|
-
else
|
21
|
-
prompt.say('List of active SSH keys:')
|
22
|
-
fetch_results.each.with_index(1) do |result, index|
|
23
|
-
prompt.ok(" #{index}) #{result}")
|
24
|
-
end
|
25
|
-
end
|
12
|
+
Helper.display_current_ssh_keys(prompt)
|
26
13
|
end
|
27
14
|
|
28
15
|
private
|
@@ -5,9 +5,9 @@ module SshKeySwitcher
|
|
5
5
|
class Delete
|
6
6
|
class << self
|
7
7
|
def display_select
|
8
|
-
|
9
|
-
if
|
10
|
-
prompt.error(
|
8
|
+
files = Helper.find_ssh_keys
|
9
|
+
if files.empty?
|
10
|
+
prompt.error("No OpenSSH keys found in #{SSH_DIR}")
|
11
11
|
nil
|
12
12
|
else
|
13
13
|
msg = 'Choose the OpenSSH keys to REMOVE. Press [CTRL+C] to exit.'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SshKeySwitcher
|
4
|
+
module Options
|
5
|
+
class List
|
6
|
+
class << self
|
7
|
+
def display
|
8
|
+
ssh_keys = Helper.find_ssh_keys
|
9
|
+
if ssh_keys.empty?
|
10
|
+
prompt.error("No OpenSSH keys found in #{SSH_DIR}")
|
11
|
+
nil
|
12
|
+
else
|
13
|
+
prompt.say('List of OpenSSH keys:')
|
14
|
+
Helper.display_list_keys(prompt, ssh_keys, color: :blue)
|
15
|
+
end
|
16
|
+
|
17
|
+
print "\n"
|
18
|
+
Helper.display_current_ssh_keys(prompt)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
include SshKeySwitcher::Contains
|
24
|
+
include SshKeySwitcher::Utils
|
25
|
+
|
26
|
+
def prompt
|
27
|
+
@prompt ||= TTY::Prompt.new(interrupt: :exit)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -7,7 +7,10 @@ module SshKeySwitcher
|
|
7
7
|
def pong
|
8
8
|
server_names = SERVER_NAMES.map { |server| "git@#{server}" }
|
9
9
|
result = prompt.select('Connect to', server_names, default: 'git@github.com')
|
10
|
-
Cmd.exec("ssh -T #{result}"
|
10
|
+
stdout, stderr, status = Cmd.exec("ssh -T #{result}")
|
11
|
+
return prompt.ok(stdout) if status.success?
|
12
|
+
|
13
|
+
prompt.error(stderr)
|
11
14
|
end
|
12
15
|
|
13
16
|
private
|
@@ -5,23 +5,26 @@ module SshKeySwitcher
|
|
5
5
|
class Select
|
6
6
|
class << self
|
7
7
|
def display_select
|
8
|
-
ssh_keys = Helper.
|
8
|
+
ssh_keys = Helper.find_ssh_keys
|
9
9
|
if ssh_keys.empty?
|
10
|
-
prompt.error(
|
10
|
+
prompt.error("No OpenSSH keys found in #{SSH_DIR}")
|
11
11
|
nil
|
12
12
|
else
|
13
13
|
prompt.select('Select an OpenSSH key:', select_options) do |menu|
|
14
14
|
menu.enum '.'
|
15
15
|
select_choices(menu, ssh_keys)
|
16
16
|
end
|
17
|
-
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
20
|
def add(path_open_ssh_key)
|
21
|
+
return if path_open_ssh_key.nil?
|
22
|
+
|
22
23
|
SshKeySwitcher::Utils::SshAgent.remove_all
|
23
|
-
SshKeySwitcher::Utils::SshAgent.add(path_open_ssh_key)
|
24
|
-
prompt.ok('OpenSSH key
|
24
|
+
_stdout, stderr, status = SshKeySwitcher::Utils::SshAgent.add(path_open_ssh_key)
|
25
|
+
return prompt.ok('Add OpenSSH key successfully!') if status.success?
|
26
|
+
|
27
|
+
prompt.error(stderr)
|
25
28
|
end
|
26
29
|
|
27
30
|
private
|
@@ -44,10 +47,10 @@ module SshKeySwitcher
|
|
44
47
|
}
|
45
48
|
end
|
46
49
|
|
47
|
-
def select_choices(menu,
|
48
|
-
|
49
|
-
display_text =
|
50
|
-
menu.choice display_text,
|
50
|
+
def select_choices(menu, ssh_keys)
|
51
|
+
ssh_keys.each do |key|
|
52
|
+
display_text = Helper.filename(key)
|
53
|
+
menu.choice display_text, key
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -7,12 +7,8 @@ module SshKeySwitcher
|
|
7
7
|
module Cmd
|
8
8
|
module_function
|
9
9
|
|
10
|
-
def exec(command,
|
10
|
+
def exec(command, _opts = {})
|
11
11
|
stdout, stderr, status = Open3.capture3(command)
|
12
|
-
if opts[:print]
|
13
|
-
print stderr
|
14
|
-
print stdout
|
15
|
-
end
|
16
12
|
[stdout, stderr, status]
|
17
13
|
end
|
18
14
|
end
|
@@ -7,20 +7,61 @@ module SshKeySwitcher
|
|
7
7
|
|
8
8
|
module_function
|
9
9
|
|
10
|
-
def
|
11
|
-
|
10
|
+
def find_ssh_keys
|
11
|
+
files = fetch_private_ssh_keys_via_header
|
12
|
+
files += fetch_private_ssh_keys_via_filename
|
13
|
+
files.flatten.uniq.sort
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetch_private_ssh_keys_via_header
|
17
|
+
ssh_dir = File.expand_path(SSH_DIR)
|
18
|
+
Dir.glob("#{ssh_dir}/**/*").select do |file|
|
19
|
+
next if File.directory?(file)
|
20
|
+
|
21
|
+
File.open(file, 'rb') do |f|
|
22
|
+
# Read the first 20 bytes from the file
|
23
|
+
header = f.read(20)
|
24
|
+
header.include?(STRING_DETECT_OPENSSH_KEY)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_private_ssh_keys_via_filename
|
30
|
+
ssh_dir = File.expand_path(SSH_DIR)
|
31
|
+
Dir.glob("#{ssh_dir}/**/*.pub").map { |file| file.gsub('.pub', '') }
|
32
|
+
end
|
12
33
|
|
13
|
-
|
34
|
+
def filename(key)
|
35
|
+
key.gsub("#{SSH_DIR}/", '').gsub('.pub', '').strip
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_active_keys
|
39
|
+
results = []
|
40
|
+
payload = Cmd.exec('ssh-add -l')[0]
|
41
|
+
payload.each_line { |line| results << line.split.last(2).join(' ') }
|
42
|
+
results
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_current_ssh_keys(prompt, color: :green)
|
46
|
+
ssh_keys = Helper.current_active_keys
|
47
|
+
|
48
|
+
if ssh_keys[0].include?('no identities')
|
49
|
+
prompt.warn('No active SSH keys')
|
50
|
+
elsif ssh_keys.size == 1
|
51
|
+
prompt.say("Active SSH key: #{ssh_keys[0]}", color: color)
|
52
|
+
else
|
53
|
+
prompt.say('List of active SSH keys:')
|
54
|
+
Helper.display_list_keys(prompt, ssh_keys, color: color)
|
55
|
+
end
|
14
56
|
end
|
15
57
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
58
|
+
def display_list_keys(prompt, ssh_keys, color: :blue)
|
59
|
+
max_space_size = ssh_keys.size.to_s.size
|
60
|
+
ssh_keys.each.with_index(1) do |key, idx|
|
61
|
+
space_size = max_space_size - (idx < 10 ? 0 : idx.to_s.size - 1)
|
62
|
+
filename = Helper.filename(key)
|
63
|
+
prompt.say(format(" %d.%#{space_size}s%s", idx, ' ', filename), color: color)
|
21
64
|
end
|
22
|
-
rescue StandardError
|
23
|
-
false
|
24
65
|
end
|
25
66
|
end
|
26
67
|
end
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module SshKeySwitcher
|
4
4
|
module Utils
|
5
5
|
class SshAgent
|
6
|
-
def self.
|
7
|
-
Cmd.exec(
|
6
|
+
def self.start_ssh_agent
|
7
|
+
Cmd.exec('eval $(ssh-agent -s)')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.add(private_key)
|
11
|
+
Cmd.exec("ssh-add #{private_key}")
|
8
12
|
end
|
9
13
|
|
10
14
|
def self.remove_all
|
@@ -14,6 +18,11 @@ module SshKeySwitcher
|
|
14
18
|
def self.del(path)
|
15
19
|
Cmd.exec("ssh-add -d #{path}")
|
16
20
|
end
|
21
|
+
|
22
|
+
def self.start_ssh_agent_if_needed
|
23
|
+
ssh_agent_pid = ENV.fetch('SSH_AGENT_PID', nil)
|
24
|
+
start_ssh_agent if ssh_agent_pid.nil? || !system("ps -p #{ssh_agent_pid} > /dev/null 2>&1")
|
25
|
+
end
|
17
26
|
end
|
18
27
|
end
|
19
28
|
end
|
data/lib/ssh_key_switcher.rb
CHANGED
@@ -10,6 +10,7 @@ module SshKeySwitcher
|
|
10
10
|
class Error < StandardError; end
|
11
11
|
|
12
12
|
class CLI < Thor
|
13
|
+
SshKeySwitcher::Utils::SshAgent.start_ssh_agent_if_needed
|
13
14
|
ENV['THOR_SILENCE_DEPRECATION'] = 'true'
|
14
15
|
|
15
16
|
desc 'version [-v, --version]', 'Show version'
|
@@ -31,6 +32,12 @@ module SshKeySwitcher
|
|
31
32
|
SshKeySwitcher::Options::Select.add(path_open_ssh_key)
|
32
33
|
end
|
33
34
|
|
35
|
+
desc 'list [-l, --list]', 'List of OpenSSH key files'
|
36
|
+
map %w[-l --list] => :list
|
37
|
+
def list
|
38
|
+
SshKeySwitcher::Options::List.display
|
39
|
+
end
|
40
|
+
|
34
41
|
desc 'current [-c, --current]', 'List of active OpenSSH keys'
|
35
42
|
map %w[-c --current] => :current
|
36
43
|
def current
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssh_key_switcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Minh Tang Q.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/ssh_key_switcher.rb
|
53
53
|
- lib/ssh_key_switcher/options/current_agent.rb
|
54
54
|
- lib/ssh_key_switcher/options/delete.rb
|
55
|
+
- lib/ssh_key_switcher/options/list.rb
|
55
56
|
- lib/ssh_key_switcher/options/ping.rb
|
56
57
|
- lib/ssh_key_switcher/options/remove.rb
|
57
58
|
- lib/ssh_key_switcher/options/select.rb
|
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
84
|
- !ruby/object:Gem::Version
|
84
85
|
version: '0'
|
85
86
|
requirements: []
|
86
|
-
rubygems_version: 3.
|
87
|
+
rubygems_version: 3.4.6
|
87
88
|
signing_key:
|
88
89
|
specification_version: 4
|
89
90
|
summary: A simple and efficient for managing and switching between OpenSSH keys seamlessly
|