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
216 217 218 |
# File 'lib/dotgpg/dir.rb', line 216 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.
175 176 177 178 179 |
# File 'lib/dotgpg/dir.rb', line 175 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.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/dotgpg/dir.rb', line 145 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 |
# File 'lib/dotgpg/dir.rb', line 55 def decrypt(path, output) 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
205 206 207 |
# File 'lib/dotgpg/dir.rb', line 205 def dotgpg path + ".gpg" end |
#dotgpg? ⇒ Boolean
Does the .gpg directory exist?
212 213 214 |
# File 'lib/dotgpg/dir.rb', line 212 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.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/dotgpg/dir.rb', line 84 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?
166 167 168 |
# File 'lib/dotgpg/dir.rb', line 166 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])
198 199 200 |
# File 'lib/dotgpg/dir.rb', line 198 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.
107 108 109 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 |
# File 'lib/dotgpg/dir.rb', line 107 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.
186 187 188 189 190 |
# File 'lib/dotgpg/dir.rb', line 186 def remove_key(key) reencrypt all_encrypted_files do key_path(key).unlink end end |