dotgpg 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 48a037835fdef38056c761c71cdfc41e2d89ebeb
4
- data.tar.gz: 919fda0ab9bf3fcbb599b4a746f83b19e52e3ab0
3
+ metadata.gz: 9809f26fb51e8fce8cce8bcbfb6656b1de07208f
4
+ data.tar.gz: 98e7d6a9928c1a64de793e7e57729756949cdbf1
5
5
  SHA512:
6
- metadata.gz: f4343d6eafe255048b2375caf4e84d4dee83485e876accf414e831d7a384be819c7ea405078c8b1f74228bc054a57e6294a9ac09fe0bb9bc7c28005d4cb648b5
7
- data.tar.gz: 737f43db0c26b457b5c6ea37a45e4d7bde855adbed68185ec2c02941a7a0db5d7aab1cc7412030c43b4d85ffd0fe64a5ee2156508f2c5ea4b01a0fe6f8b4bcbc
6
+ metadata.gz: 2133b5d5e87cc941c0aebed9e2e12680d56abaf62fa42fca66cd1822d828e0eca3478c7c81e5cb3069bec3c0057be59de42c7ee72be4894f638410d875f23cbe
7
+ data.tar.gz: b8030f114a7fb96bdd9100f216529b566077a015f000f6d458f2b741d785d48b20e87cfcae7b22e55e04f8dcc1af1aba44eb2a63012a9bea7829423db0dd76fb
data/README.md CHANGED
@@ -80,6 +80,10 @@ leJCaaNJQBbIOj4QOjFWiZ8ATqLH9nkgawSwOV3xp0MWayCJ3MVnibt4CaI=
80
80
  -----END PGP PUBLIC KEY BLOCK-----
81
81
  ```
82
82
 
83
+ #### dotgpg merge
84
+
85
+ See the 'Integration With Git' section below.
86
+
83
87
  ## Why
84
88
 
85
89
  Production secrets are the keys that your app needs to run. For example the session cookie encryption key, or the database password. These are critical to the running of your app, so it's essential to have a backup that is version controlled. Then if anything goes wrong, you can find the previous values and go back to running happily.
@@ -165,3 +169,25 @@ Occasionally people leave, or stop needing access to dotgpg. To remove them use
165
169
  dotgpg rm conrad.irwin@gmail.com
166
170
  ```
167
171
 
172
+ ### Integration with git
173
+
174
+ Encrypted files don't work well with many git workflows because they are (basically) binary files that appear to be text files. Because of this diff and merge may appear to work from git's point of view but will actually generate garbage according to GPG. It's possible to work around this:
175
+
176
+ Add the following lines to your [git config](http://git-scm.com/docs/git-config):
177
+ ```
178
+ [diff "gpg"]
179
+ textconv = gpg -d -q --batch --no-tty 2>/dev/null
180
+ [merge "gpg"]
181
+ name = dotgpg merge driver
182
+ driver = "dotgpg merge %O %A %B"
183
+ ```
184
+ (you may need to use `bundle exec dotgpg merge %O %A %B` depending on how you've installed dotgpg and ruby)
185
+
186
+ Add the following lines to your [git attributes](http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes)
187
+ ```
188
+ *.gpg diff=gpg merge=gpg
189
+ ```
190
+
191
+ Now `git diff` will show you the diff of the decrypted content. `git merge` will decrypted your files, try to merge the decrypted text, and then encrypt the subsequent output. If there's a conflict the file will be marked as such but will still be a valid GPG file - the decrypted file will contain the text with the merge conflict markers in it.
192
+
193
+ It's probably possible to adapt this to other VCS's.
data/dotgpg.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'dotgpg'
3
- gem.version = '0.5.1'
3
+ gem.version = '0.6.0'
4
4
 
5
5
  gem.summary = 'gpg-encrypted backup for your dotenv files'
6
6
  gem.description = "Easy management of gpg-encrypted backup files"
data/lib/dotgpg/cli.rb CHANGED
@@ -23,7 +23,7 @@ class Dotgpg
23
23
  info " #{directory}/.gpg/#{key.email}"
24
24
 
25
25
  FileUtils.mkdir_p(dir.dotgpg)
26
- unless File.exist? 'README.md'
26
+ unless File.exist? 'README.md'
27
27
  FileUtils.cp Pathname.new(__FILE__).dirname.join("template/README.md"), dir.path.join("README.md")
28
28
  dir.add_key(key)
29
29
  end
@@ -100,6 +100,14 @@ class Dotgpg
100
100
  fail e.message
101
101
  end
102
102
 
103
+ desc "unsafe_cat FILES...", "unsafely decrypt and print files"
104
+ def unsafe_cat(*files)
105
+ return if helped?
106
+ files.each do |f|
107
+ $stdout.puts Dotgpg.decrypt_without_validating_signatures File.open f
108
+ end
109
+ end
110
+
103
111
  desc "edit FILES...", "edit and re-encrypt files"
104
112
  def edit(*files)
105
113
  return if helped?
@@ -122,6 +130,100 @@ class Dotgpg
122
130
  fail e.message
123
131
  end
124
132
 
133
+ desc "merge MYFILE OLDFILE YOURFILE", "dotgpg-aware wrapper for merging via diff3(1)"
134
+ def merge(*files)
135
+ require 'find'
136
+ require 'digest'
137
+ require 'fileutils'
138
+
139
+ return if helped?
140
+ fail "usage: MYFILE OLDFILE YOURFILE" unless files.length == 3
141
+
142
+ # ok, we won't know which gpg directory was used for our files because
143
+ # the .merge_files are dumped in the root git dir. so we resort to ulginess
144
+ # - we hash OLDFILE, search for directories which contain a .gpg subdir
145
+ # and check the md5sums of all the files in said directory. if there's a
146
+ # match we have our dir
147
+ old_hash = Digest::SHA256.file(files[1]).hexdigest
148
+
149
+ # if file is nil DotGpg:Dir.closest throws an error. if it's just a blank
150
+ # string we get the "not in a dotgpg directory" message
151
+ file = ''
152
+
153
+ Find.find(::Dir.pwd) do |path|
154
+ if FileTest.directory?(path) && File.basename(path) == ".gpg"
155
+ # found a .gpg dir, check in the parent for our target file
156
+ dotgpg_dir = File.dirname path
157
+ gpg_files = ::Dir.glob(File.join dotgpg_dir, "*")
158
+
159
+ if matched = gpg_files.find { |f| File.file?(f) && old_hash == Digest::SHA256.file(f).hexdigest }
160
+ file = matched
161
+ break
162
+ end
163
+ end
164
+ end
165
+
166
+ dir = Dotgpg::Dir.closest(file)
167
+ fail "not in a dotgpg directory" unless dir
168
+
169
+ mine = Tempfile.open('mine')
170
+ old = Tempfile.open('old')
171
+ yours = Tempfile.open('yours')
172
+
173
+ begin
174
+ # decrypt all three of our files
175
+ dir.decrypt files[0], mine
176
+ dir.decrypt files[1], old
177
+ dir.decrypt files[2], yours
178
+
179
+ # flush our io
180
+ mine.flush
181
+ old.flush
182
+ yours.flush
183
+
184
+ # TODO - could also use diff3(1) here:
185
+ #
186
+ # "diff3 -L mine -L old -L yours -m #{mine.path} #{old.path} #{yours.path}"
187
+ #
188
+ # but git merge-file's output is more diff3-ish than diff3's, weird.
189
+ cmd = "git merge-file -L mine -L old -L yours -p %s %s %s 2>/dev/null" %
190
+ [ Shellwords.escape(mine.path), Shellwords.escape(old.path),
191
+ Shellwords.escape(yours.path) ]
192
+
193
+ # run our merge
194
+ diff = `#{cmd}`
195
+ conflict = !$?.success?
196
+ ensure
197
+ # close and unlink our tempfiles
198
+ mine.close!
199
+ old.close!
200
+ yours.close!
201
+ end
202
+
203
+ # make a new stringio object out of our diff output
204
+ io = StringIO.new diff
205
+
206
+ # create a new tempfile to write our merged file to
207
+ t = Tempfile.open('merged')
208
+ begin
209
+ # encrypt our diff3 output
210
+ dir.encrypt t, io
211
+ t.flush
212
+
213
+ # and copy that file back to OLDFILE (aka files[1]) since that's where
214
+ # git expects to find it
215
+ FileUtils.copy t.path, files[1]
216
+ ensure
217
+ t.close!
218
+ end
219
+
220
+ # this is important - this exit value is what git uses to decide if there
221
+ # is a conflict or not
222
+ exit (conflict ? 1 : 0)
223
+ rescue GPGME::Error::BadPassphrase => e
224
+ fail e.message
225
+ end
226
+
125
227
  private
126
228
 
127
229
  # If the global --help or -h flag is passed, show help.
data/lib/dotgpg.rb CHANGED
@@ -94,4 +94,17 @@ class Dotgpg
94
94
  io.puts(@passphrase)
95
95
  io.flush
96
96
  end
97
+
98
+ # this is a quick workaroundfor situations where finding a dotgpg directory is
99
+ # difficult.
100
+ #
101
+ # THIS WILL NOT VERIFY THE INPUT WAS SIGNED
102
+ # THIS WILL NOT VERIFY THE INPUT SIGNATURE IS VALID
103
+ # THIS WILL NOT VERIFY THE INPUT SIGNATURE IS TRUSTED
104
+ #
105
+ # see Dir#decrypt for the right way to read files.
106
+
107
+ def self.decrypt_without_validating_signatures(data)
108
+ GPGME::Crypto.new.decrypt data, passphrase_callback: Dotgpg.method(:passfunc)
109
+ end
97
110
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotgpg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Conrad Irwin
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - certs/gem-public_cert.pem
12
- date: 2014-12-12 00:00:00.000000000 Z
12
+ date: 2015-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor