2pass 1.2.0 → 2.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 +4 -4
- data/2pass.gemspec +2 -0
- data/README.md +5 -2
- data/bin/2pass +22 -17
- data/lib/2pass/version.rb +1 -1
- data/lib/2pass.rb +47 -26
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1236ce26a8191128890f5d302ae31ebe607f51dd6018bdbc1dd561f782909748
|
4
|
+
data.tar.gz: b5b6cb1c22ce47f83df9a1f403ffce5628ae1d7a9d496b3ccbcc7c79f6a4726b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da6f2bacdade151d6ab41d815aec44f4f21dbd5b14ee330a06a4bf34efcda2b1d7d7f1eefbf455058002ca524f1369e577245692f5329b6a2938348c5799a6c9
|
7
|
+
data.tar.gz: 165926fcf9576c49b62a628beb4ec16cff3ea01a58d07854f88c5e7891d73c40af22406183dfbacd138794fb477c90094e8d208844eac9188adc828c6dd22765
|
data/2pass.gemspec
CHANGED
@@ -24,4 +24,6 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rake", "~> 13.0"
|
25
25
|
spec.add_development_dependency "minitest", "~> 5.0"
|
26
26
|
spec.add_development_dependency "minitest-reporters", "~> 1.3", ">= 1.3.0"
|
27
|
+
|
28
|
+
spec.add_dependency "terminal-table", "~> 4.0"
|
27
29
|
end
|
data/README.md
CHANGED
@@ -17,13 +17,12 @@ An array of hashes with the following keys:
|
|
17
17
|
|
18
18
|
- id
|
19
19
|
- value
|
20
|
-
- uuid
|
21
20
|
|
22
21
|
```sh
|
23
22
|
touch ~/.2pass/vault_name.yml
|
24
23
|
```
|
25
24
|
|
26
|
-
Alternatively, if you have a vault file in a different location, you can link it.
|
25
|
+
Alternatively, if you already have a vault file in a different location, you can link it.
|
27
26
|
|
28
27
|
```sh
|
29
28
|
2pass link vault_name /path/to/vault_name.yml
|
@@ -44,6 +43,10 @@ Then build the gem and install it.
|
|
44
43
|
2pass list <vault_name>
|
45
44
|
2pass add <vault_name> <id> <value>
|
46
45
|
```
|
46
|
+
You can also pass an optional environment to most commands:
|
47
|
+
`2pass get myproject mykey production`
|
48
|
+
|
49
|
+
This will search for `mykey` within `myproject.production.yml`
|
47
50
|
|
48
51
|
## Development
|
49
52
|
|
data/bin/2pass
CHANGED
@@ -5,12 +5,13 @@ require_relative "../lib/2pass"
|
|
5
5
|
def help_message
|
6
6
|
puts <<~HELP
|
7
7
|
Usage:
|
8
|
-
2pass add <vault_name> <id> <value> - Add new secret
|
9
|
-
2pass get <vault_name> <id> - Get content by ID from the specified vault
|
10
|
-
2pass list <vault_name> - List the content of the specified vault as key
|
11
|
-
2pass list <vault_name> --json - List the content of the specified vault as JSON
|
12
|
-
2pass
|
13
|
-
2pass -
|
8
|
+
2pass add <vault_name> <id> <value> <env> - Add new secret. env is optional
|
9
|
+
2pass get <vault_name> <id> <env> - Get content by ID from the specified vault. env is optional
|
10
|
+
2pass list <vault_name> <env> - List the content of the specified vault as key=value pairs. env is optional
|
11
|
+
2pass list <vault_name> <env> --json - List the content of the specified vault as JSON. env is optional
|
12
|
+
2pass list <vault_name> <env> --dotenv - List the content of the specified vault as key=value pairs. env is optional
|
13
|
+
2pass link <vault_name> <target_path> <env> - Create a symlink for an existing vault. Useful when the vault is stored in a synced place (iCloud, Dropbox, etc.). env is optional
|
14
|
+
2pass -h - Display this help message
|
14
15
|
HELP
|
15
16
|
end
|
16
17
|
|
@@ -24,12 +25,12 @@ OptionParser.new do |opts|
|
|
24
25
|
opts.on("-v", "--version", "Display the version") do
|
25
26
|
options[:version] = true
|
26
27
|
end
|
27
|
-
opts.on("
|
28
|
-
options[:format] = format == "json" ? :json : :text
|
29
|
-
end
|
30
|
-
opts.on("--json", "Use JSON output format (same as -f json)") do
|
28
|
+
opts.on("--json", "Use JSON output format") do
|
31
29
|
options[:format] = :json
|
32
30
|
end
|
31
|
+
opts.on("--dotenv", "Use key=value output format") do
|
32
|
+
options[:format] = :dotenv
|
33
|
+
end
|
33
34
|
end.parse!
|
34
35
|
|
35
36
|
if options[:help]
|
@@ -56,19 +57,23 @@ begin
|
|
56
57
|
help_message
|
57
58
|
exit(1)
|
58
59
|
end
|
59
|
-
id = args[0]
|
60
|
-
puts TwoPass.get_secret(vault_name, id)
|
60
|
+
id, env = args[0], args[1]
|
61
|
+
puts TwoPass.get_secret(vault_name, id, env: env)
|
61
62
|
when :add
|
62
63
|
if args.length != 2
|
63
64
|
help_message
|
64
65
|
exit(1)
|
65
66
|
end
|
66
|
-
|
67
|
+
id, value, env = args[0], args[1], args[2]
|
68
|
+
TwoPass.add_secret(vault_name, id, value, env: env)
|
67
69
|
when :list
|
70
|
+
env = args[0]
|
68
71
|
if options[:format] == :json
|
69
|
-
puts TwoPass.list_content(vault_name, format: :json)
|
72
|
+
puts TwoPass.list_content(vault_name, env: env, format: :json)
|
73
|
+
elsif options[:format] == :dotenv
|
74
|
+
puts TwoPass.list_content(vault_name, env: env, format: :dotenv)
|
70
75
|
else
|
71
|
-
puts TwoPass.list_content(vault_name)
|
76
|
+
puts TwoPass.list_content(vault_name, env: env)
|
72
77
|
end
|
73
78
|
exit(1)
|
74
79
|
when :link
|
@@ -76,8 +81,8 @@ begin
|
|
76
81
|
help_message
|
77
82
|
exit(1)
|
78
83
|
end
|
79
|
-
target_path = args[0]
|
80
|
-
TwoPass.create_symlink(vault_name, target_path)
|
84
|
+
target_path, env = args[0], args[1]
|
85
|
+
TwoPass.create_symlink(vault_name, target_path, env: env)
|
81
86
|
when :help
|
82
87
|
help_message
|
83
88
|
else
|
data/lib/2pass/version.rb
CHANGED
data/lib/2pass.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "optparse"
|
2
4
|
require "json"
|
3
5
|
require "yaml"
|
4
6
|
require "fileutils"
|
5
|
-
require "
|
7
|
+
require "terminal-table"
|
6
8
|
|
7
9
|
require_relative "2pass/version"
|
8
10
|
|
@@ -10,9 +12,9 @@ module TwoPass
|
|
10
12
|
VAULT_DIR = "#{Dir.home}/.2pass"
|
11
13
|
|
12
14
|
class << self
|
13
|
-
def create_symlink(vault_name, target_path)
|
15
|
+
def create_symlink(vault_name, target_path, env: nil)
|
14
16
|
FileUtils.mkdir_p(VAULT_DIR)
|
15
|
-
symlink_path =
|
17
|
+
symlink_path = vault_file_path(vault_name, env: env)
|
16
18
|
|
17
19
|
if File.exist?(symlink_path)
|
18
20
|
puts "Symlink already exists: #{symlink_path}"
|
@@ -22,30 +24,31 @@ module TwoPass
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
def
|
26
|
-
file_path = "#{VAULT_DIR}/#{vault_name}.yml"
|
27
|
-
return [] unless File.exist?(file_path)
|
28
|
-
|
29
|
-
YAML.load_file(file_path, symbolize_names: true) || []
|
30
|
-
rescue Psych::SyntaxError => e
|
31
|
-
STDERR.puts "Error parsing YAML file: #{e.message}"
|
32
|
-
[]
|
33
|
-
end
|
34
|
-
|
35
|
-
def save_vault(vault_name, data)
|
27
|
+
def save_vault(vault_name, data, env: nil)
|
36
28
|
FileUtils.mkdir_p(VAULT_DIR)
|
37
|
-
file_path =
|
29
|
+
file_path = vault_file_path(vault_name, env: env)
|
38
30
|
File.write(file_path, YAML.dump(data))
|
39
31
|
end
|
40
32
|
|
41
|
-
def list_content(vault_name, format: :
|
42
|
-
vault = load_vault(vault_name)
|
43
|
-
if format == :
|
33
|
+
def list_content(vault_name, env: nil, format: :table)
|
34
|
+
vault = load_vault(vault_name, env: env)
|
35
|
+
if format == :table
|
36
|
+
rows = vault
|
37
|
+
.sort_by { |hash| hash[:id] }
|
38
|
+
.each_with_object([]) do |h, arr|
|
39
|
+
arr << [h[:id], h[:value]]
|
40
|
+
end
|
41
|
+
Terminal::Table.new(
|
42
|
+
rows: rows,
|
43
|
+
title: env || nil,
|
44
|
+
style: {all_separators: true}
|
45
|
+
).to_s
|
46
|
+
elsif format == :dotenv
|
44
47
|
vault
|
45
48
|
.map { |h| "#{h[:id]}=#{h[:value]}" }
|
46
49
|
.sort
|
47
50
|
.join("\n")
|
48
|
-
|
51
|
+
elsif format == :json
|
49
52
|
JSON.pretty_generate(
|
50
53
|
vault
|
51
54
|
.map { |hash| hash.slice(:id, :value) }
|
@@ -54,23 +57,22 @@ module TwoPass
|
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
57
|
-
def add_secret(vault_name, id, value)
|
60
|
+
def add_secret(vault_name, id, value, env: nil)
|
58
61
|
new_secret = {
|
59
62
|
id: id,
|
60
|
-
value: value
|
61
|
-
uuid: SecureRandom.uuid
|
63
|
+
value: value
|
62
64
|
}
|
63
|
-
data = load_vault(vault_name)
|
65
|
+
data = load_vault(vault_name, env: env)
|
64
66
|
existing_entry_id = data.find_index { |hash| hash[:id] == new_secret[:id] }
|
65
67
|
if existing_entry_id
|
66
68
|
raise "The secret already exists"
|
67
69
|
end
|
68
70
|
data << new_secret
|
69
|
-
save_vault(vault_name, data)
|
71
|
+
save_vault(vault_name, data, env: env)
|
70
72
|
end
|
71
73
|
|
72
|
-
def get_secret(vault_name, id)
|
73
|
-
vault = load_vault(vault_name)
|
74
|
+
def get_secret(vault_name, id, env: nil)
|
75
|
+
vault = load_vault(vault_name, env: env)
|
74
76
|
entry = vault.find { |hash| hash[:id] == id }
|
75
77
|
if entry
|
76
78
|
entry[:value]
|
@@ -78,5 +80,24 @@ module TwoPass
|
|
78
80
|
raise "Entry not found"
|
79
81
|
end
|
80
82
|
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def load_vault(vault_name, env: nil)
|
87
|
+
file_path = self.vault_file_path(vault_name, env: env)
|
88
|
+
return [] unless File.exist?(file_path)
|
89
|
+
|
90
|
+
YAML.load_file(file_path, symbolize_names: true) || []
|
91
|
+
rescue Psych::SyntaxError => e
|
92
|
+
STDERR.puts "Error parsing YAML file: #{e.message}"
|
93
|
+
[]
|
94
|
+
end
|
95
|
+
|
96
|
+
def vault_file_path(vault_name, env: nil)
|
97
|
+
[
|
98
|
+
VAULT_DIR,
|
99
|
+
[vault_name, env].compact.join(".")
|
100
|
+
].join("/") + ".yml"
|
101
|
+
end
|
81
102
|
end
|
82
103
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: 2pass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Olivier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 1.3.0
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: terminal-table
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '4.0'
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '4.0'
|
75
89
|
description: 2pass is a CLI application for managing YAML-based vaults.
|
76
90
|
email:
|
77
91
|
- contact@yafoy.com
|