ssh_key_switcher 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f533df5b3d9d76377ed35a3267899f82d5a7603a80c29894de402e854710f1d9
4
+ data.tar.gz: 2f077163c2255fc4498b7f8f9c1e6828387706fc669f1ad7f8e8d6fdcf89adf0
5
+ SHA512:
6
+ metadata.gz: b721f9d2f12001dce27f73847a54ad3be8aff4d24cc865c234d986ffa69ebefb8198eba89e6104f8507d96a1fa3bf69fd48634a6af8c49bc8aaee8b02645e980
7
+ data.tar.gz: fbd9c084f585f68be76dd671f251100640ca3551f479107d35db48f70d706188129d0a689b04e490dced827dbbe9726d4c29dd1d2c05c1b8966a182161c443c9
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # SSH Key Switcher
2
+
3
+ A simple and efficient Ruby gem for managing and switching between OpenSSH keys seamlessly
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ssh_key_switcher'
11
+
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ ```bash
17
+ $ bundle install
18
+
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```bash
24
+ $ gem install ssh_key_switcher
25
+
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Show Help
31
+
32
+ ```bash
33
+ $ sks -h [--help]
34
+
35
+ ```
36
+
37
+ ### Show Version
38
+
39
+ ```bash
40
+ $ sks -v [--version]
41
+
42
+ ```
43
+
44
+ Displays the current version of SSH Key Switcher.
45
+
46
+ ### Ping Server
47
+
48
+ ```bash
49
+ $ sks -p [--ping]
50
+
51
+ ```
52
+
53
+ Tests the connection to servers listed in **`SshKeySwitcher::Contains::SERVER_NAMES`**.
54
+
55
+ ### Select OpenSSH Key
56
+
57
+ ```bash
58
+ $ sks -s [--select]
59
+
60
+ ```
61
+
62
+ Allows you to interactively select and set an OpenSSH key for your sessions.
63
+
64
+ ### List Active OpenSSH Keys
65
+
66
+ ```bash
67
+ $ sks -c [--current]
68
+
69
+ ```
70
+
71
+ Displays a list of currently active SSH keys.
72
+
73
+ ### Remove OpenSSH Key
74
+
75
+ ```bash
76
+ $ sks --rm [--remove]
77
+
78
+ ```
79
+
80
+ Interactive prompt to remove an OpenSSH key from the list of managed keys.
81
+
82
+ ## Contributing
83
+
84
+ Bug reports and pull requests are welcome on GitHub at [SSH Key Switcher](https://github.com/TOMOSIA-VIETNAM/ssh_key_switcher).
85
+
86
+ ## License
87
+
88
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
89
+
90
+ ## Development
91
+
92
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
93
+
94
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
data/bin/sks ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require_relative '../lib/ssh_key_switcher'
6
+
7
+ SshKeySwitcher::CLI.start
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Options
5
+ class CurrentAgent
6
+ class << self
7
+ def fetch_results
8
+ results = []
9
+ payload = Cmd.exec('ssh-add -l')[0]
10
+ payload.each_line { |line| results << line.split[-2..].join(' ') }
11
+ results
12
+ end
13
+
14
+ def display
15
+ if fetch_results[0].include?('no identities')
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
26
+ end
27
+
28
+ private
29
+
30
+ include SshKeySwitcher::Utils
31
+
32
+ def prompt
33
+ @prompt ||= TTY::Prompt.new
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Options
5
+ class Delete
6
+ class << self
7
+ def display_select
8
+ keys = Helper.find_open_ssh_keys
9
+ if keys.empty?
10
+ prompt.error('No OpenSSH keys found in ~/.ssh')
11
+ nil
12
+ else
13
+ msg = 'Choose the OpenSSH keys to REMOVE. Press [CTRL+C] to exit.'
14
+ prompt.multi_select(msg, select_options) do |menu|
15
+ menu.enum '.'
16
+ select_choices(menu, keys)
17
+ end
18
+ end
19
+ end
20
+
21
+ def del(path_open_ssh_keys)
22
+ is_no = prompt.no?('Are you sure you want to delete it permanently?')
23
+
24
+ if is_no
25
+ prompt.say('Cancelled!')
26
+ else
27
+ path_open_ssh_keys.each do |path|
28
+ SshKeySwitcher::Utils::SshAgent.del(path)
29
+ Cmd.exec("rm #{path}")
30
+ Cmd.exec("rm #{path}.pub")
31
+ end
32
+ prompt.ok('OpenSSH key removed successfully!')
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ include SshKeySwitcher::Contains
39
+ include SshKeySwitcher::Utils
40
+
41
+ def prompt
42
+ @prompt ||= TTY::Prompt.new(interrupt: :exit)
43
+ end
44
+
45
+ def select_options
46
+ {
47
+ cycle: true,
48
+ symbols: { marker: '●' },
49
+ per_page: 100,
50
+ filter: true,
51
+ help: 'Use ↑/↓ arrow keys, and letter keys to filter',
52
+ show_help: :always
53
+ }
54
+ end
55
+
56
+ def select_choices(menu, keys)
57
+ keys.each do |value|
58
+ display_text = value.split('/')[-2..].join('/').gsub('.ssh/', '')
59
+ menu.choice display_text, value
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Options
5
+ class Ping
6
+ class << self
7
+ def pong
8
+ server_names = SERVER_NAMES.map { |server| "git@#{server}" }
9
+ result = prompt.select('Connect to', server_names, default: 'git@github.com')
10
+ Cmd.exec("ssh -T #{result}", print: true)
11
+ end
12
+
13
+ private
14
+
15
+ include SshKeySwitcher::Contains
16
+ include SshKeySwitcher::Utils
17
+
18
+ def prompt
19
+ @prompt ||= TTY::Prompt.new(interrupt: :exit)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Options
5
+ class Remove
6
+ class << self
7
+ def display_select
8
+ keys = Helper.find_open_ssh_keys
9
+ if keys.empty?
10
+ prompt.error('No OpenSSH keys found in ~/.ssh')
11
+ nil
12
+ else
13
+ prompt.multi_select('Choose the OpenSSH keys to delete. Press [CTRL+C] to exit.',
14
+ select_options) do |menu|
15
+ menu.enum '.'
16
+ select_choices(menu, keys)
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ def del(path_open_ssh_keys)
23
+ is_no = prompt.no?('Are you sure you want to remove these keys?')
24
+
25
+ if is_no
26
+ prompt.say('Cancelled!')
27
+ else
28
+ path_open_ssh_keys.each do |path|
29
+ SshKeySwitcher::Utils::SshAgent.del(path)
30
+ Cmd.exec("rm #{path}")
31
+ Cmd.exec("rm #{path}.pub")
32
+ end
33
+ prompt.ok('OpenSSH key removed successfully!')
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ include SshKeySwitcher::Contains
40
+ include SshKeySwitcher::Utils
41
+
42
+ def prompt
43
+ @prompt ||= TTY::Prompt.new(interrupt: :exit)
44
+ end
45
+
46
+ def select_options
47
+ {
48
+ cycle: true,
49
+ symbols: { marker: '●' },
50
+ per_page: 100,
51
+ filter: true,
52
+ help: 'Use ↑/↓ arrow keys, and letter keys to filter',
53
+ show_help: :always
54
+ }
55
+ end
56
+
57
+ def select_choices(menu, keys)
58
+ keys.each do |value|
59
+ display_text = value.split('/')[-2..].join('/').gsub('.ssh/', '')
60
+ menu.choice display_text, value
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Options
5
+ class Select
6
+ class << self
7
+ def display_select
8
+ ssh_keys = Helper.find_open_ssh_keys
9
+ if ssh_keys.empty?
10
+ prompt.error('No OpenSSH keys found in ~/.ssh')
11
+ nil
12
+ else
13
+ prompt.select('Select an OpenSSH key:', select_options) do |menu|
14
+ menu.enum '.'
15
+ select_choices(menu, ssh_keys)
16
+ end
17
+
18
+ end
19
+ end
20
+
21
+ def add(path_open_ssh_key)
22
+ SshKeySwitcher::Utils::SshAgent.remove_all
23
+ SshKeySwitcher::Utils::SshAgent.add(path_open_ssh_key)
24
+ prompt.ok('OpenSSH key added successfully!')
25
+ end
26
+
27
+ private
28
+
29
+ include SshKeySwitcher::Contains
30
+ include SshKeySwitcher::Utils
31
+
32
+ def prompt
33
+ @prompt ||= TTY::Prompt.new(interrupt: :exit)
34
+ end
35
+
36
+ def select_options
37
+ {
38
+ cycle: true,
39
+ symbols: { marker: '➜' },
40
+ per_page: 20,
41
+ filter: true,
42
+ help: 'Use ↑/↓ arrow keys, and letter keys to filter',
43
+ show_help: :always
44
+ }
45
+ end
46
+
47
+ def select_choices(menu, keys)
48
+ keys.each do |value|
49
+ display_text = value.split('/')[-2..].join('/').gsub('.ssh/', '')
50
+ menu.choice display_text, value
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module SshKeySwitcher
6
+ module Utils
7
+ module Cmd
8
+ module_function
9
+
10
+ def exec(command, opts = {})
11
+ stdout, stderr, status = Open3.capture3(command)
12
+ if opts[:print]
13
+ print stderr
14
+ print stdout
15
+ end
16
+ [stdout, stderr, status]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Contains
5
+ SSH_DIR = '~/.ssh'
6
+ STRING_DETECT_OPENSSH_KEY = 'OPENSSH'
7
+ SERVER_NAMES = %w[github.com gitlab.com bitbucket.org].freeze
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Utils
5
+ module Helper
6
+ include SshKeySwitcher::Contains
7
+
8
+ module_function
9
+
10
+ def find_open_ssh_keys
11
+ ssh_folder = File.expand_path(SSH_DIR)
12
+
13
+ Dir.glob("#{ssh_folder}/*").select { |file| valid_ssh_key?(file) }.sort
14
+ end
15
+
16
+ def valid_ssh_key?(file)
17
+ File.open(file, 'rb') do |f|
18
+ # Read the first 20 bytes from the file
19
+ header = f.read(20)
20
+ header.include?(STRING_DETECT_OPENSSH_KEY)
21
+ end
22
+ rescue StandardError
23
+ false
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SshKeySwitcher
4
+ module Utils
5
+ class SshAgent
6
+ def self.add(key)
7
+ Cmd.exec("ssh-add #{key}")
8
+ end
9
+
10
+ def self.remove_all
11
+ Cmd.exec('ssh-add -D')
12
+ end
13
+
14
+ def self.del(path)
15
+ Cmd.exec("ssh-add -d #{path}")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module SshKeySwitcher
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-prompt'
4
+ require 'thor'
5
+ require_relative 'ssh_key_switcher/version'
6
+ Dir.glob("#{__dir__}/ssh_key_switcher/utils/*.rb").sort.each { |file| require_relative(file) }
7
+ Dir.glob("#{__dir__}/ssh_key_switcher/options/*.rb").sort.each { |file| require_relative(file) }
8
+
9
+ module SshKeySwitcher
10
+ class Error < StandardError; end
11
+
12
+ class CLI < Thor
13
+ desc 'version [-v, --version]', 'Show version'
14
+ map %w[-v --version] => :version
15
+ def version
16
+ TTY::Prompt.new.say("SSHKeySwitcher version #{VERSION}")
17
+ end
18
+
19
+ desc 'ping [-p, --ping]', "Connect to servers #{SshKeySwitcher::Contains::SERVER_NAMES}"
20
+ map %w[-p --ping] => :ping
21
+ def ping
22
+ SshKeySwitcher::Options::Ping.pong
23
+ end
24
+
25
+ desc 'select [-s, --select]', 'Select an OpenSSH key'
26
+ map %w[-s --select] => :select
27
+ def select
28
+ path_open_ssh_key = SshKeySwitcher::Options::Select.display_select
29
+ SshKeySwitcher::Options::Select.add(path_open_ssh_key)
30
+ end
31
+
32
+ desc 'current [-c, --current]', 'List of active OpenSSH keys'
33
+ map %w[-c --current] => :current
34
+ def current
35
+ SshKeySwitcher::Options::CurrentAgent.display
36
+ end
37
+
38
+ desc 'remove [-rm, --remove]', 'Remove an OpenSSH key'
39
+ map %w[-rm --remove] => :remove
40
+ def remove
41
+ path_open_ssh_key = SshKeySwitcher::Options::Remove.display_select
42
+ SshKeySwitcher::Options::Remove.del(path_open_ssh_key)
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ssh_key_switcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Minh Tang Q.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-prompt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.23.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.23.1
41
+ description: Simple and efficient for managing and switching between OpenSSH keys
42
+ seamlessly
43
+ email:
44
+ - minh.tang1@tomosia.com
45
+ - vhquocminhit@gmail.com
46
+ executables:
47
+ - sks
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - README.md
52
+ - bin/sks
53
+ - lib/ssh_key_switcher.rb
54
+ - lib/ssh_key_switcher/options/current_agent.rb
55
+ - lib/ssh_key_switcher/options/delete.rb
56
+ - lib/ssh_key_switcher/options/ping.rb
57
+ - lib/ssh_key_switcher/options/remove.rb
58
+ - lib/ssh_key_switcher/options/select.rb
59
+ - lib/ssh_key_switcher/utils/cmd.rb
60
+ - lib/ssh_key_switcher/utils/contains.rb
61
+ - lib/ssh_key_switcher/utils/helper.rb
62
+ - lib/ssh_key_switcher/utils/ssh_agent.rb
63
+ - lib/ssh_key_switcher/version.rb
64
+ homepage: https://github.com
65
+ licenses:
66
+ - MIT
67
+ metadata:
68
+ rubygems_mfa_required: 'true'
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.6.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.3.20
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Simple and efficient for managing and switching between OpenSSH keys seamlessly
88
+ test_files: []