Skip to content

Commit

Permalink
0.5.0 (#15)
Browse files Browse the repository at this point in the history
* add export command

* default command plays like pass

* add support of "key"

Co-authored-by: Sylvain Maucourt <sylvain.maucourt@herow.io>
  • Loading branch information
sylvek and Sylvain Maucourt authored Dec 31, 2021
1 parent 33c3559 commit 9fa3b34
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 9 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,29 @@ $> leeloo keystore default test
|test |/Users/sylvek/test |* |
+-------+------------------------------+-------+
$> leeloo key
# will display available keys and which are set to this keystore
+-------------------------+--------+
|Email |Selected|
+-------------------------+--------+
|user1@email.com | |
|user2@email.com | |
+-------------------------+--------+
(if nothing is displayed, have a look on your gpg's configuration)
$> leeloo key add user1@email.com
# will add user1@email.com to this keystore
+-------------------------+--------+
|Email |Selected|
+-------------------------+--------+
|user1@email.com |* |
|user2@email.com | |
+-------------------------+--------+
$> leeloo key sync
# will update all secrets to be readable by selected users
$> leeloo write my_secret
# will add a secret
Expand Down
84 changes: 80 additions & 4 deletions leeloo/lib/leeloo/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,24 @@ def run
program :help, 'GitHub', 'https://github.com/sylvek'
program :help_formatter, :compact

default_command :"list"
default_command :wrapper

command :wrapper do |c|
c.action do |args, options|
unless args == []
name = args.first
ctl = SecretController.new(options)
ctl.read(name)
ctl.display
else
SecretsController.new(options).display
end
end
end

command :list do |c|
c.syntax = 'leeloo list [options]'
c.description = "Display secrets list of keystore"
c.description = "Display secrets list of stored on a keystore"
c.option '--ascii', nil, 'display secrets without unicode tree'
c.option '--keystore STRING', String, 'a selected keystore'

Expand Down Expand Up @@ -101,6 +114,58 @@ def run
end
end

command :key do |c|
c.syntax = 'leeloo keys'
c.description = "list keys from this keystore"
c.option '--ascii', nil, 'display secrets without unicode tree'
c.option '--keystore STRING', String, 'a selected keystore'

c.action do |args, options|
ctl = KeysController.new(options)
ctl.display
end
end

command "key sync" do |c|
c.syntax = 'leeloo keys sync'
c.description = "synchronize secrets with keys"
c.option '--keystore STRING', String, 'a selected keystore'

c.action do |args, options|
ctl = KeysController.new(options)
ctl.sync
ctl.display
end
end

command "key add" do |c|
c.syntax = 'leeloo key add <email>'
c.description = "add a dedicated key"
c.option '--keystore STRING', String, 'a selected keystore'

c.action do |args, options|
abort "email is missing" unless args.length == 1
email = args.first
ctl = KeysController.new(options)
ctl.add_key(email)
ctl.display
end
end

command "key remove" do |c|
c.syntax = 'leeloo key remove <email>'
c.description = "remove a dedicated key"
c.option '--keystore STRING', String, 'a selected keystore'

c.action do |args, options|
abort "email is missing" unless args.length == 1
email = args.first
ctl = KeysController.new(options)
ctl.remove_key(email)
ctl.display
end
end

command :read do |c|
c.syntax = 'leeloo read <name>'
c.description = "Display a secret from a keystore"
Expand Down Expand Up @@ -160,7 +225,7 @@ def run
end
end

command :sync do |c|
command "keystore sync" do |c|
c.syntax = 'leeloo sync'
c.description = "Synchronize a keystore"
c.option '--keystore STRING', String, 'a selected keystore'
Expand All @@ -172,7 +237,18 @@ def run
end
end

command :init do |c|
command "keystore export" do |c|
c.syntax = 'leeloo export'
c.description = "Export all secrets from a keystore"
c.option '--keystore STRING', String, 'a selected keystore'

c.action do |args, options|
ctl = ExportController.new(options)
ctl.display
end
end

command "keystore init" do |c|
c.syntax = 'leeloo init'
c.description = "Initialize a keystore"
c.option '--keystore STRING', String, 'a selected keystore'
Expand Down
32 changes: 31 additions & 1 deletion leeloo/lib/leeloo/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,46 @@ def initialize options
class SecretsController < PrivateLocalFileSystemController
def initialize options
super options
@secrets = @preferences.keystore(@options.keystore).secrets
@secrets = @keystore.secrets
end
def search name
@secrets = @secrets.select { |secret| secret.name.downcase.include? name.downcase } || []
end
def list
@secrets
end
def display
@output.render_secrets @secrets
end
end

class ExportController < PrivateLocalFileSystemController
def display
@keystore.secrets.each do |secret|
@output.render_name_and_secret(secret.name, @keystore.secret_from_name(secret.name))
end
end
end

class KeysController < PrivateLocalFileSystemController
def add_key email
@keystore.add_key(email)
end
def remove_key email
@keystore.remove_key(email)
end
def sync
@keystore.secrets.each do |secret|
phrase = @keystore.secret_from_name(secret.name).read
@keystore.secret_from_name(secret.name).write(phrase)
end
end
def display
@keys = @keystore.keys
@output.render_keys @keys
end
end

class SecretController < PrivateLocalFileSystemController
def read name
@secret = @keystore.secret_from_name(name)
Expand Down
51 changes: 50 additions & 1 deletion leeloo/lib/leeloo/keystore.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ def secrets
find_secrets "#{@path}/secrets"
end

def keys
[]
end

def find_secrets path
elements = []
Dir.glob("#{path}/**") do |element|
Expand Down Expand Up @@ -121,15 +125,41 @@ class GpgPrivateLocalFileSystemKeystore < PrivateLocalFileSystemKeystore
def initialize name, path
super name, path
FileUtils.mkdir_p "#{@path}/keys"
populate_recipients
end

def populate_recipients
@recipients = []
Dir.glob("#{path}/keys/*") { |key| @recipients << File.basename(key) }
@recipients.each { |key| GPGME::Key.import(File.open("#{path}/keys/#{key}")) }
end

def init
super
GPGME::Key.find(:public, nil, ).each { |key| key.export(:output => File.open("#{path}/keys/#{key.uids.first.email}", "w+")) }
File.write("#{@path}/keys/do_not_remove_me", "do not remove me")
end

def keys
available = GPGME::Key.find(:public, nil, ).map { |key| key.email }
actual = Dir.glob("#{@path}/keys/**").map { |path| path.split('/').last }
available.map { |email| actual.include?(email) ? "#{email}::true" : "#{email}::false" }
end

def add_key email
paths = []
GPGME::Key.find(:public, email).each do |key|
key.export(:output => File.open("#{path}/keys/#{key.uids.first.email}", "w+"))
paths << "#{path}/keys/#{key.uids.first.email}"
end
return paths
end

def remove_key email
if File.exist?("#{path}/keys/#{email}")
File.delete("#{path}/keys/#{email}")
return "#{path}/keys/#{email}"
end
return nil
end

def secret_of path
Expand Down Expand Up @@ -172,6 +202,25 @@ def secret_from_name element
secret_of @keystore.secret_from_name(element)
end

def keys
@keystore.keys
end

def add_key email
@keystore.add_key(email).each do |path|
@git.add path
@git.commit "#{email} added"
end
end

def remove_key email
deleted = @keystore.remove_key email
if deleted
@git.add deleted
@git.commit "#{email} removed"
end
end

def secrets
@keystore.secrets
end
Expand Down
30 changes: 28 additions & 2 deletions leeloo/lib/leeloo/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ def render_secret secret
def render_text text
end

def render_name_and_secret name, secret
end

def render_keys keys
end

def render_footprint footprint
end

Expand All @@ -46,10 +52,20 @@ def render_secret secret
end
end

def render_name_and_secret name, secret
self.render_text name
self.render_secret secret
self.render_text '------'
end

def render_text text
puts text
end

def render_keys keys
self.render_text keys
end

def render_footprint footprint
puts "token:"
puts Base64.strict_encode64 footprint.to_json
Expand All @@ -69,11 +85,21 @@ def render_preferences preferences
end

def render_secrets secrets
hash = {:secrets => []}
secrets.sort_by(&:name).each { |secret| sort(hash[:secrets], secret.name) }
hash = {'Password Store' => []}
secrets.sort_by(&:name).each { |secret| sort(hash['Password Store'], secret.name) }
puts TTY::Tree.new(hash).render
end

def render_keys keys
rows = []
keys.each do |key|
splitted = key.split('::')
is_present = '*' if splitted[1] == 'true'
rows << [splitted[0], is_present]
end
puts TTY::Table.new(header: ['Email', 'Selected'], rows: rows).render(:ascii)
end

def sort array, element
if element
e = element.split("/", 2)
Expand Down
2 changes: 1 addition & 1 deletion leeloo/lib/leeloo/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Leeloo
VERSION = '0.4.1'.freeze
VERSION = '0.5.0'.freeze
DESCRIPTION = "The easiest way to share securely your secrets".freeze
end

0 comments on commit 9fa3b34

Please sign in to comment.