Class: Dotgpg::Dir
- Inherits:
-
Object
- Object
- Dotgpg::Dir
- Defined in:
- lib/dotgpg/dir.rb
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
-
.closest(path = ".", *others) ⇒ nil|[Dotgpg::Dir]
Find the Dotgpg::Dir that contains the given path.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#add_key(key) ⇒ Object
Add a given key to the directory.
-
#all_encrypted_files(dir = path) ⇒ Array<Pathname>
List every GPG-encrypted file in a directory recursively.
-
#decrypt(path, output) ⇒ Boolean
Decrypt the contents of path and write to output.
-
#dotgpg ⇒ Pathname
The .gpg directory.
-
#dotgpg? ⇒ Boolean
Does the .gpg directory exist?.
-
#encrypt(path, input) ⇒ Boolean
Encrypt the input and write it to the given path.
-
#has_key?(key) ⇒ Boolean
Does this directory includea key for the given user yet?.
-
#initialize(path) ⇒ Dir
constructor
Open a Dotgpg::Dir.
-
#key_path(key) ⇒ Pathname
The path at which a key should be stored.
-
#known_keys ⇒ Array<GPGME::Key>
Get the keys currently associated with this directory.
-
#reencrypt(files) {|the| ... } ⇒ Object
Re-encrypts a set of files with the currently known keys.
-
#remove_key(key) ⇒ Object
Remove a given key from a directory.
Constructor Details
#initialize(path) ⇒ Dir
Open a Dotgpg::Dir
34 35 36 |
# File 'lib/dotgpg/dir.rb', line 34 def initialize(path) @path = Pathname.new(File.absolute_path(path)).cleanpath end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
4 5 6 |
# File 'lib/dotgpg/dir.rb', line 4 def path @path end |
Class Method Details
.closest(path = ".", *others) ⇒ nil|[Dotgpg::Dir]
Find the Dotgpg::Dir that contains the given path.
If multiple are given only returns the directory if it contains all paths.
If no path is given, find the Dotgpg::Dir that contains the current working directory.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/dotgpg/dir.rb', line 16 def self.closest(path=".", *others) path = Pathname.new(File.absolute_path(path)).cleanpath result = path.ascend do |parent| maybe = Dotgpg::Dir.new(parent) break maybe if maybe.dotgpg? end if others.any? && closest(*others) != result nil else result end end |
Instance Method Details
#==(other) ⇒ Object
219 220 221 |
# File 'lib/dotgpg/dir.rb', line 219 def ==(other) Dotgpg::Dir === other && other.path == self.path end |
#add_key(key) ⇒ Object
Add a given key to the directory
Re-encrypts all files to add the new key as a recipient.
178 179 180 181 182 |
# File 'lib/dotgpg/dir.rb', line 178 def add_key(key) reencrypt all_encrypted_files do File.write key_path(key), key.export(armor: true).to_s end end |
#all_encrypted_files(dir = path) ⇒ Array<Pathname>
List every GPG-encrypted file in a directory recursively.
Assumes the files are armored (non-armored files are hard to detect and dotgpg itself always armors)
This is used to decide which files to re-encrypt when adding a user.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/dotgpg/dir.rb', line 148 def all_encrypted_files(dir=path) results = [] dir.each_child do |child| if child.directory? if !child.symlink? && child != dotgpg results += all_encrypted_files(child) end elsif child.readable? if child.read(1024) =~ /-----BEGIN PGP MESSAGE-----/ results << child end end end results end |
#decrypt(path, output) ⇒ Boolean
Decrypt the contents of path and write to output.
The path should be absolute, and may point to outside this directory, though that is not recommended.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/dotgpg/dir.rb', line 55 def decrypt(path, output) # make sure all keys are imported before we try to decrypt - otherwise we # might fail with an invalid signature known_keys File.open(path) do |f| signature = false temp = GPGME::Crypto.new.decrypt f, passphrase_callback: Dotgpg.method(:passfunc) do |s| signature = s end unless ENV["DOTGPG_ALLOW_INJECTION_ATTACK"] raise InvalidSignature, "file was not signed" unless signature raise InvalidSignature, "signature was incorrect" unless signature.valid? raise InvalidSignature, "signed by a stranger" unless known_keys.include?(signature.key) end output.write temp.read end true rescue GPGME::Error::NoData, GPGME::Error::DecryptFailed, SystemCallError => e Dotgpg.warn path, e false end |
#dotgpg ⇒ Pathname
The .gpg directory
208 209 210 |
# File 'lib/dotgpg/dir.rb', line 208 def dotgpg path + ".gpg" end |
#dotgpg? ⇒ Boolean
Does the .gpg directory exist?
215 216 217 |
# File 'lib/dotgpg/dir.rb', line 215 def dotgpg? dotgpg.directory? end |
#encrypt(path, input) ⇒ Boolean
Encrypt the input and write it to the given path.
The path should be absolute, and may point to outside this directory, though that is not recommended.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/dotgpg/dir.rb', line 87 def encrypt(path, input) File.open(path, "w") do |f| GPGME::Crypto.new.encrypt input, output: f, recipients: known_keys, armor: true, always_trust: true, sign: true, passphrase_callback: Dotgpg.method(:passfunc), signers: known_keys.detect{ |key| GPGME::Key.find(:secret).include?(key) } end true rescue SystemCallError => e Dotgpg.warn path, e false end |
#has_key?(key) ⇒ Boolean
Does this directory includea key for the given user yet?
169 170 171 |
# File 'lib/dotgpg/dir.rb', line 169 def has_key?(key) File.exist? key_path(key) end |
#key_path(key) ⇒ Pathname
The path at which a key should be stored
(i.e. .gpg/[email protected])
201 202 203 |
# File 'lib/dotgpg/dir.rb', line 201 def key_path(key) dotgpg + key.email end |
#known_keys ⇒ Array<GPGME::Key>
Get the keys currently associated with this directory.
41 42 43 44 45 |
# File 'lib/dotgpg/dir.rb', line 41 def known_keys dotgpg.each_child.map do |key_file| Dotgpg::Key.read key_file.open end end |
#reencrypt(files) {|the| ... } ⇒ Object
Re-encrypts a set of files with the currently known keys.
If a block is provided, it can be used to edit the files in their temporary un-encrypted state.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/dotgpg/dir.rb', line 110 def reencrypt(files, &block) tempfiles = {} files.uniq.each do |f| temp = Tempfile.new([File.basename(f), ".sh"]) tempfiles[f] = temp if File.exist? f decrypted = decrypt f, temp tempfiles.delete f unless decrypted end temp.flush temp.close(false) end yield tempfiles if block_given? tempfiles.each_pair do |f, temp| temp.open temp.seek(0) encrypt f, temp end nil ensure tempfiles.values.each do |temp| temp.close(true) end end |
#remove_key(key) ⇒ Object
Remove a given key from a directory
Re-encrypts all files so that the removed key no-longer has access.
189 190 191 192 193 |
# File 'lib/dotgpg/dir.rb', line 189 def remove_key(key) reencrypt all_encrypted_files do key_path(key).unlink end end |