bcdatabase 1.0.6 → 1.1.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.
- data/CHANGELOG.markdown +31 -12
- data/README.markdown +120 -25
- data/bcdatabase.gemspec +30 -0
- data/bin/bcdatabase +15 -21
- data/lib/bcdatabase/cli.rb +81 -0
- data/lib/bcdatabase/commands/encrypt.rb +47 -0
- data/lib/bcdatabase/commands/epass.rb +40 -0
- data/lib/bcdatabase/commands/gen_key.rb +48 -0
- data/lib/bcdatabase/commands.rb +7 -233
- data/lib/bcdatabase/version.rb +1 -1
- data/lib/bcdatabase.rb +108 -23
- metadata +81 -12
data/CHANGELOG.markdown
CHANGED
@@ -1,55 +1,74 @@
|
|
1
|
+
Bcdatabase history
|
2
|
+
==================
|
3
|
+
|
4
|
+
1.1.0
|
5
|
+
-----
|
6
|
+
|
7
|
+
- Introduce "transforms" -- a way to attach behavior to modify entries
|
8
|
+
on load. See {Bcdatabase.load} for details.
|
9
|
+
- Add `:datamapper` built-in transform to support sharing one set of
|
10
|
+
entries between ActiveRecord and DataMapper. (#10)
|
11
|
+
- Rework command-line interface for better testability. It's now
|
12
|
+
compatible with MRI 1.9. (#11, #7)
|
13
|
+
- Provide a better message when working with encrypted passwords and
|
14
|
+
the keyfile is not readable. (#1)
|
15
|
+
- Improve `bcdatabase encrypt` so that it will work with a wider
|
16
|
+
variety of input passwords and YAML files. The remaining limitations
|
17
|
+
are documented in its online help. (#12)
|
18
|
+
- Interpret empty stanzas as entries made up entirely of defaults. (#13)
|
19
|
+
|
1
20
|
1.0.6
|
2
|
-
|
21
|
+
-----
|
3
22
|
- Use `ENV['RAILS_ENV']` instead of the unreliable `RAILS_ENV` constant.
|
4
23
|
|
5
24
|
1.0.5
|
6
|
-
|
25
|
+
-----
|
7
26
|
- Loosen highline dependency so that bcdatabase can be used in buildr buildfiles.
|
8
27
|
|
9
28
|
1.0.4
|
10
|
-
|
29
|
+
-----
|
11
30
|
- Fix command line utilities that were broken in 1.0.3 due to
|
12
31
|
inadequate test coverage. (GH-4)
|
13
32
|
|
14
33
|
1.0.3
|
15
|
-
|
34
|
+
-----
|
16
35
|
- Support ActiveSupport 3. ActiveSupport 2 continues to work.
|
17
36
|
|
18
37
|
1.0.2
|
19
|
-
|
38
|
+
-----
|
20
39
|
- Tighten up gemspec gem deps. Bcdatabase does not currently work
|
21
40
|
with ActiveSupport 3.
|
22
41
|
|
23
42
|
1.0.1
|
24
|
-
|
43
|
+
-----
|
25
44
|
- Update some old syntax for ruby 1.9 compatibility (David Yip)
|
26
45
|
|
27
46
|
1.0.0
|
28
|
-
|
47
|
+
-----
|
29
48
|
- Split out from NUBIC internal `bcdatabase` project.
|
30
49
|
(Changelog entries below reflect the relevant changes & version numbers from that project.)
|
31
50
|
|
32
51
|
0.4.1
|
33
|
-
|
52
|
+
-----
|
34
53
|
- Fix `bcdatabase encrypt` so that it doesn't re-encrypt already encrypted
|
35
54
|
epassword entries.
|
36
55
|
|
37
56
|
0.4.0
|
38
|
-
|
57
|
+
-----
|
39
58
|
- Use the YAML entry name as the "database" value if no other value is
|
40
59
|
provided. This is to DRY up PostgreSQL configurations where the username
|
41
60
|
(already defaulted) and the database name are the same.
|
42
61
|
|
43
62
|
0.2.0
|
44
|
-
|
63
|
+
-----
|
45
64
|
- Change default encrypted secret password location
|
46
65
|
|
47
66
|
0.1.0
|
48
|
-
|
67
|
+
-----
|
49
68
|
- Support encrypted passwords
|
50
69
|
- Command-line utility (also called bcdatabase) for creating encrypted passwords
|
51
70
|
- Gem distribution
|
52
71
|
|
53
72
|
0.0.0
|
54
|
-
|
73
|
+
-----
|
55
74
|
Original release.
|
data/README.markdown
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
-
|
1
|
+
Bcdatabase
|
2
2
|
==========
|
3
3
|
|
4
|
-
*
|
4
|
+
*Bcdatabase* is a library and utility which provides database
|
5
|
+
configuration parameter management for Ruby on Rails applications. It
|
6
|
+
provides a simple mechanism for separating database configuration
|
7
|
+
attributes from application source code so that there's no temptation
|
8
|
+
to check passwords into the version control system. And it
|
9
|
+
centralizes the parameters for a single server so that they can be
|
10
|
+
easily shared among multiple applications and easily updated by a
|
11
|
+
single administrator.
|
5
12
|
|
6
13
|
## Installing bcdatabase
|
7
14
|
|
@@ -9,7 +16,7 @@ bcdatabase
|
|
9
16
|
|
10
17
|
## Using bcdatabase to configure the database for a Rails application
|
11
18
|
|
12
|
-
A bog-standard
|
19
|
+
A bog-standard Rails application's `config/database.yml` file looks like this:
|
13
20
|
|
14
21
|
development:
|
15
22
|
adapter: oracle_enhanced
|
@@ -29,7 +36,10 @@ A bog-standard rails application's `config/database.yml` file looks like this:
|
|
29
36
|
username: cfg_animal
|
30
37
|
password: very-secret
|
31
38
|
|
32
|
-
Rails allows this file to contain [ERB][]. `bcdatabase` uses ERB to
|
39
|
+
Rails allows this file to contain [ERB][]. `bcdatabase` uses ERB to
|
40
|
+
replace an entire configuration block. If you wanted to replace, say,
|
41
|
+
just the production block in this example, you would transform it like
|
42
|
+
so:
|
33
43
|
|
34
44
|
<%
|
35
45
|
require 'bcdatabase'
|
@@ -50,7 +60,9 @@ Rails allows this file to contain [ERB][]. `bcdatabase` uses ERB to replace an
|
|
50
60
|
|
51
61
|
<%= bcdb.production :prod, :cfg_animal %>
|
52
62
|
|
53
|
-
This means "create a YAML block for the *production* environment from
|
63
|
+
This means "create a YAML block for the *production* environment from
|
64
|
+
the configuration entry named *cfg_animal* in
|
65
|
+
/etc/nubic/db/*prod*.yml." The method called can be anything:
|
54
66
|
|
55
67
|
<%= bcdb.development :local, :cfg_animal %>
|
56
68
|
<%= bcdb.staging 'stage', 'cfg_animal' %>
|
@@ -60,21 +72,33 @@ This means "create a YAML block for the *production* environment from the config
|
|
60
72
|
|
61
73
|
## Directly accessing configuration parameters from bcdatabase
|
62
74
|
|
63
|
-
More rarely, you might need to access the actual configuration hash,
|
75
|
+
More rarely, you might need to access the actual configuration hash,
|
76
|
+
instead of the YAMLized version. You can access it by invoking
|
77
|
+
`Bcdatabase.load` as shown earlier, then using the bracket operator to
|
78
|
+
specify the configuration you want:
|
64
79
|
|
65
80
|
bcdb[:local, :cfg_animal]
|
66
81
|
|
67
|
-
The resulting hash is suitable for passing to
|
82
|
+
The resulting hash is suitable for passing to
|
83
|
+
`ActiveRecord::Base.establish_connection`, for instance.
|
68
84
|
|
69
85
|
## Central configuration files
|
70
86
|
|
71
|
-
The database configuration properties for all the applications on a
|
87
|
+
The database configuration properties for all the applications on a
|
88
|
+
server are stored in one or more files under `/etc/nubic/db` (by
|
89
|
+
default; see "File locations" below). Each one is a standard YAML
|
90
|
+
file, similar to Rails' `database.yml` but with a few enhancements:
|
72
91
|
|
73
|
-
* Each file can have a defaults entry which provides attributes which
|
74
|
-
|
75
|
-
* Each entry defaults its "
|
92
|
+
* Each file can have a defaults entry which provides attributes which
|
93
|
+
are shared across all configurations in the file
|
94
|
+
* Each entry defaults its "username" attribute to the name of the
|
95
|
+
entry (useful for Oracle)
|
96
|
+
* Each entry defaults its "database" attribute to the name of the
|
97
|
+
entry (useful for PostgreSQL)
|
76
98
|
|
77
|
-
Since each file can define a set of default properties which are
|
99
|
+
Since each file can define a set of default properties which are
|
100
|
+
shared by all the contained configurations, it makes sense to group
|
101
|
+
databases which have some shared configuration elements.
|
78
102
|
|
79
103
|
### Example
|
80
104
|
|
@@ -96,7 +120,7 @@ You have defined two configuration entries. `:stage, :cfg_animal`:
|
|
96
120
|
password: secret
|
97
121
|
database: //mondo/stage
|
98
122
|
|
99
|
-
and `:
|
123
|
+
and `:stage, :personnel`:
|
100
124
|
|
101
125
|
adapter: oracle_enhanced
|
102
126
|
username: pers
|
@@ -105,33 +129,104 @@ and `:bcstage, :personnel`:
|
|
105
129
|
|
106
130
|
## Obscuring passwords
|
107
131
|
|
108
|
-
|
132
|
+
Bcdatabase supports storing encrypted passwords instead of the
|
133
|
+
plaintext ones shown in the previous example. Encrypted passwords are
|
134
|
+
defined with the key `epassword` instead of `password`. The library
|
135
|
+
will decrypt the `epassword` value and expose it to the calling code
|
136
|
+
(usually Rails) unencrypted under the `password` key. The
|
137
|
+
`bcdatabase` command line utility handles encrypting passwords; see
|
138
|
+
the next section.
|
109
139
|
|
110
|
-
While the passwords are technically encrypted, the master key must be
|
140
|
+
While the passwords are technically encrypted, the master key must be
|
141
|
+
stored on the same machine so that they can be decrypted on demand.
|
142
|
+
That means this feature only obscures passwords — it will not
|
143
|
+
deter a determined attacker.
|
111
144
|
|
112
145
|
## `bcdatabase` command line utility
|
113
146
|
|
114
|
-
The gem includes a command line utility (also called `bcdatabase`)
|
147
|
+
The gem includes a command line utility (also called `bcdatabase`)
|
148
|
+
which assists with creating `epassword` entries. It has online help;
|
149
|
+
after installing the gem, try `bcdatabase help` to read it:
|
115
150
|
|
116
151
|
$ bcdatabase help
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
help List commands or display help for one
|
152
|
+
Tasks:
|
153
|
+
bcdatabase encrypt [INPUT [OUTPUT]] # Encrypt every password in a bcdatabase YAML file
|
154
|
+
bcdatabase epass [-] # Generate epasswords from database passwords
|
155
|
+
bcdatabase gen-key [-] # Generate the bcdatabase shared key
|
156
|
+
bcdatabase help [TASK] # Describe available tasks or one specific task
|
123
157
|
|
124
158
|
## File locations
|
125
159
|
|
126
|
-
`/etc/nubic/db` is the default place the library will look for the
|
160
|
+
`/etc/nubic/db` is the default place the library will look for the
|
161
|
+
central configuration files. It may be overridden with the
|
162
|
+
environment variable `BCDATABASE_PATH`. For instance, if you wanted
|
163
|
+
to keep these files in your home directory on your development machine
|
164
|
+
— perhaps so that editing them doesn't require elevated
|
165
|
+
privileges — you could add this to `~/.bashrc`:
|
127
166
|
|
128
167
|
export BCDATABASE_PATH=${HOME}/nubic/db
|
129
168
|
|
130
|
-
Similarly, the file containing the encryption password has a sensible
|
169
|
+
Similarly, the file containing the encryption password has a sensible
|
170
|
+
default location, but that location can be overridden by setting
|
171
|
+
`BCDATABASE_PASS`.
|
172
|
+
|
173
|
+
## DataMapper
|
174
|
+
|
175
|
+
Bcdatabase was originally designed for use with ActiveRecord in Rails
|
176
|
+
applications. Since [DataMapper][dm]'s programmatic configuration mechanism
|
177
|
+
(`Datamapper.setup`) accepts hashes which are very similar to
|
178
|
+
ActiveRecord configuration hashes, Bcdatabase can easily be used with
|
179
|
+
DataMapper as well. Example:
|
180
|
+
|
181
|
+
bcdb = Bcdatabase.load(:transforms => [:datamapper]))
|
182
|
+
DataMapper.setup(:default, bcdb[:stage, :personnel])
|
183
|
+
|
184
|
+
The `:datamapper` transform passed to `Bcdatabase.load` in this
|
185
|
+
example permits sharing of one set of Bcdatabase configurations
|
186
|
+
between ActiveRecord and DataMapper-based apps. Specifically, for
|
187
|
+
those cases where the ActiveRecord adapter and the DataMapper adapter
|
188
|
+
have different names, it allows you to specify a separate
|
189
|
+
`datamapper_adapter` in your Bcdatabase configuration. For example,
|
190
|
+
say you had these contents in `stage.yml`:
|
191
|
+
|
192
|
+
defaults:
|
193
|
+
adapter: postgresql
|
194
|
+
datamapper_adapter: postgres
|
195
|
+
personnel:
|
196
|
+
password: foo
|
197
|
+
|
198
|
+
When loaded without the `:datamapper` transform, the effective
|
199
|
+
database configuration hash for `:stage, :personnel` would be
|
200
|
+
|
201
|
+
adapter: postgresql
|
202
|
+
datamapper_adapter: postgres # ignored by AR
|
203
|
+
database: personnel
|
204
|
+
username: personnel
|
205
|
+
|
206
|
+
With the `:datamapper` transform, the result would be instead:
|
207
|
+
|
208
|
+
adapter: postgres
|
209
|
+
database: personnel
|
210
|
+
username: personnel
|
211
|
+
|
212
|
+
And so your DM and AR apps can live side-by-side and neither needs to
|
213
|
+
embed its own database credentials.
|
214
|
+
|
215
|
+
[dm]: http://datamapper.org/
|
216
|
+
|
217
|
+
## Platforms
|
218
|
+
|
219
|
+
Bcdatabase works on MRI 1.8.7 and MRI 1.9.2. It will also work on
|
220
|
+
JRuby (tested on 1.6+), provided that `jruby-openssl` is also
|
221
|
+
installed. It is [continuously tested][ci] on all three of these
|
222
|
+
platforms.
|
223
|
+
|
224
|
+
[ci]: https://public-ci.nubic.northwestern.edu/job/bcdatabase/
|
131
225
|
|
132
226
|
## Credits
|
133
227
|
|
134
|
-
`bcdatabase` was developed at and for the [Northwestern University
|
228
|
+
`bcdatabase` was developed at and for the [Northwestern University
|
229
|
+
Biomedical Informatics Center][NUBIC].
|
135
230
|
|
136
231
|
[NUBIC]: http://www.nucats.northwestern.edu/centers/nubic/index.html
|
137
232
|
|
data/bcdatabase.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
|
4
|
+
require 'bcdatabase/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'bcdatabase'
|
8
|
+
s.version = Bcdatabase::VERSION
|
9
|
+
s.summary = %Q{Server-central database configuration for rails and other ruby apps}
|
10
|
+
s.description = %Q{bcdatabase is a tool for storing passwords and other configuration information outside of your application source tree.}
|
11
|
+
s.email = "rhett@detailedbalance.net"
|
12
|
+
s.homepage = "http://github.com/NUBIC/bcdatabase"
|
13
|
+
s.authors = ["Rhett Sutphin"]
|
14
|
+
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
|
17
|
+
s.executables = ['bcdatabase']
|
18
|
+
s.files = Dir.glob("{CHANGELOG.markdown,LICENSE,README.markdown,bcdatabase.gemspec,{bin,lib}/**/*}")
|
19
|
+
|
20
|
+
s.add_dependency "activesupport", ">= 2.0"
|
21
|
+
s.add_dependency "highline", "~> 1.5"
|
22
|
+
s.add_dependency "i18n"
|
23
|
+
s.add_dependency 'thor', '~> 0.14.6'
|
24
|
+
|
25
|
+
s.add_development_dependency 'bundler', '~> 1.0.15'
|
26
|
+
s.add_development_dependency 'rake', '~> 0.9.2'
|
27
|
+
s.add_development_dependency 'rspec','~> 2.6'
|
28
|
+
s.add_development_dependency "ci_reporter", "~> 1.6"
|
29
|
+
s.add_development_dependency 'yard', '~> 0.7.2'
|
30
|
+
end
|
data/bin/bcdatabase
CHANGED
@@ -1,26 +1,20 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# Allow this executable to be run directly from the source as well as
|
4
|
+
# from an installed gem.
|
5
|
+
begin
|
6
|
+
lib = File.expand_path('../../lib', __FILE__)
|
7
|
+
unless $LOAD_PATH.include?(lib)
|
8
|
+
$LOAD_PATH << lib
|
9
|
+
require 'rubygems'
|
10
|
+
end
|
8
11
|
end
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
command = ARGV.shift
|
13
|
-
unless command
|
14
|
-
$stderr.puts "Please specify a command."
|
15
|
-
$stderr.puts Bcdatabase::Commands.help
|
16
|
-
exit(1)
|
17
|
-
end
|
13
|
+
require 'bcdatabase'
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
$stderr.puts
|
23
|
-
exit
|
15
|
+
begin
|
16
|
+
Bcdatabase::CLI.start
|
17
|
+
rescue Interrupt => e
|
18
|
+
$stderr.puts "Interrupted"
|
19
|
+
exit 1
|
24
20
|
end
|
25
|
-
|
26
|
-
exit(klass.new(ARGV).main)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'bcdatabase'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
module Bcdatabase
|
5
|
+
class CLI < Thor
|
6
|
+
desc "encrypt [INPUT [OUTPUT]]",
|
7
|
+
"Encrypt every password in a bcdatabase YAML file"
|
8
|
+
long_desc <<-DESC
|
9
|
+
This command finds all the keys named 'password' in the input
|
10
|
+
YAML and substitutes appropriate 'epassword' keys.
|
11
|
+
|
12
|
+
If inputfile is specified, the source will be that file. If not,
|
13
|
+
the source will be standard in.
|
14
|
+
|
15
|
+
If inputfile and outputfile are specified, the new file will be
|
16
|
+
written to the output file. Otherwise the output will go to
|
17
|
+
standard out. Input and output may be the same file.
|
18
|
+
|
19
|
+
You can't read from standard in and write to a file directly;
|
20
|
+
use shell file redirection if you need to do that.
|
21
|
+
|
22
|
+
N.b.: this command works with a subset of legal YAML
|
23
|
+
files. Specifically, it will only work if the 'password' key and
|
24
|
+
value are entirely on the same line. If for some reason you
|
25
|
+
can't arrange for your input files to meet this restriction, you
|
26
|
+
can use the epass subcommand to encrypt one password at a time.
|
27
|
+
DESC
|
28
|
+
def encrypt(inputfile=nil, outputfile=nil)
|
29
|
+
Commands::Encrypt.new(inputfile, outputfile).run
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'epass [-]', 'Generate epasswords from database passwords'
|
33
|
+
long_desc <<-DESC
|
34
|
+
With no arguments, interactively prompts for passwords and
|
35
|
+
prints the corresponding epassword entry.
|
36
|
+
|
37
|
+
If the last argument is -, reads a newline-separated list of
|
38
|
+
passwords from standard in and prints the corresponding
|
39
|
+
epasswords to standard out.
|
40
|
+
DESC
|
41
|
+
def epass(arg=nil)
|
42
|
+
Commands::Epass.new(arg == '-').run
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'gen-key [-]', 'Generate the bcdatabase shared key'
|
46
|
+
long_desc <<-DESC
|
47
|
+
Generates the key that is used to obscure epasswords. By
|
48
|
+
default, the key will be generated in
|
49
|
+
#{Bcdatabase.pass_file}. If the last argument to this command
|
50
|
+
is -, the key will be generated to standard out instead.
|
51
|
+
|
52
|
+
CAUTION: writing to #{Bcdatabase.pass_file} may overwrite an
|
53
|
+
existing bcdatabase key. If that happens, you will need to
|
54
|
+
reencrypt all the epasswords on this machine.
|
55
|
+
DESC
|
56
|
+
def gen_key(arg=nil)
|
57
|
+
Commands::GenKey.new(arg == '-').run
|
58
|
+
end
|
59
|
+
|
60
|
+
no_tasks do
|
61
|
+
# Add uniform exception handling
|
62
|
+
[:encrypt, :epass, :gen_key].each do |original|
|
63
|
+
alias_method "#{original}_without_rescue".to_sym, original
|
64
|
+
|
65
|
+
class_eval <<-RUBY
|
66
|
+
def #{original}(*args)
|
67
|
+
#{original}_without_rescue(*args)
|
68
|
+
rescue SystemCallError => e
|
69
|
+
shell.say("\#{e.class}: \#{e}", :RED)
|
70
|
+
exit(8)
|
71
|
+
rescue Bcdatabase::Error => e
|
72
|
+
shell.say(e.message, :RED)
|
73
|
+
exit(4)
|
74
|
+
rescue Commands::ForcedExit => e
|
75
|
+
exit(e.code)
|
76
|
+
end
|
77
|
+
RUBY
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'bcdatabase/commands'
|
2
|
+
|
3
|
+
module Bcdatabase::Commands
|
4
|
+
class Encrypt
|
5
|
+
def initialize(inputfile=nil, outputfile=nil)
|
6
|
+
@input = (Pathname.new(inputfile) if inputfile)
|
7
|
+
@output = (Pathname.new(outputfile) if outputfile)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
begin
|
12
|
+
# try to preserve the order by replacing everything using regexes
|
13
|
+
contents = inio.read
|
14
|
+
contents.gsub!(/\bpassword:.*?$/) { |line|
|
15
|
+
"epassword: #{Bcdatabase.encrypt(YAML.load(line)['password'])}"
|
16
|
+
}
|
17
|
+
outio.write(contents)
|
18
|
+
ensure
|
19
|
+
@inio.close if @close_in && @inio
|
20
|
+
@outio.close if @close_out && @outio
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def inio
|
27
|
+
@inio ||=
|
28
|
+
if @input
|
29
|
+
@close_in = true
|
30
|
+
@input.open('r')
|
31
|
+
else
|
32
|
+
$stdin
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def outio
|
37
|
+
@outio ||=
|
38
|
+
if @output
|
39
|
+
@output.dirname.mkpath
|
40
|
+
@close_out = true
|
41
|
+
@output.open('w')
|
42
|
+
else
|
43
|
+
$stdout
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'bcdatabase/commands'
|
2
|
+
|
3
|
+
require 'highline'
|
4
|
+
|
5
|
+
module Bcdatabase::Commands
|
6
|
+
class Epass
|
7
|
+
def initialize(streaming, opts={})
|
8
|
+
@streaming = streaming
|
9
|
+
@echo = opts[:echo].nil? ? false : opts[:echo]
|
10
|
+
@hl = HighLine.new($stdin, $stderr)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
@streaming ? streamed : interactive
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def streamed
|
20
|
+
$stdin.readlines.each do |line|
|
21
|
+
puts Bcdatabase.encrypt(line.chomp)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def interactive
|
26
|
+
loop do
|
27
|
+
pass = @hl.ask("Password (^C to end): ") do |q|
|
28
|
+
# this is configurable because having it false hangs the
|
29
|
+
# unit tests.
|
30
|
+
q.echo = @echo
|
31
|
+
end
|
32
|
+
puts " epassword: #{Bcdatabase.encrypt(pass)}"
|
33
|
+
end
|
34
|
+
rescue Interrupt
|
35
|
+
$stderr.puts "Quit"
|
36
|
+
rescue EOFError
|
37
|
+
$stderr.puts "Quit"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'bcdatabase/commands'
|
2
|
+
require 'highline'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module Bcdatabase::Commands
|
6
|
+
class GenKey
|
7
|
+
def initialize(streaming)
|
8
|
+
@streaming = streaming
|
9
|
+
@hl = HighLine.new($stdin, $stderr)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
begin
|
14
|
+
key = random_key(128)
|
15
|
+
outio.write key
|
16
|
+
ensure
|
17
|
+
@outio.close if @close_out && @outio
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def random_key(length)
|
24
|
+
(1..length).collect { rand(255) }.pack('C*')
|
25
|
+
end
|
26
|
+
|
27
|
+
def outio
|
28
|
+
@outio ||=
|
29
|
+
if @streaming
|
30
|
+
$stdout
|
31
|
+
else
|
32
|
+
open_key_file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def open_key_file
|
37
|
+
filename = Pathname.new(Bcdatabase.pass_file)
|
38
|
+
if filename.exist?
|
39
|
+
unless @hl.agree("This operation will overwrite the existing pass file.\n Are you sure you want to do that? (y/n) ")
|
40
|
+
raise ForcedExit.new(1)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@close_out = true
|
44
|
+
filename.dirname.mkpath
|
45
|
+
filename.open('w')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/bcdatabase/commands.rb
CHANGED
@@ -1,241 +1,15 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'highline'
|
4
|
-
require 'active_support'
|
5
|
-
require 'active_support/core_ext/string/inflections'
|
6
1
|
require 'bcdatabase'
|
7
2
|
|
8
|
-
HL = HighLine.new
|
9
|
-
|
10
3
|
module Bcdatabase::Commands
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def self.usage(use)
|
15
|
-
"usage: #{UTILITY_NAME} #{use}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.help_message(use)
|
19
|
-
msg = [ "#{command_name}: #{summary}", usage(use), "" ]
|
20
|
-
yield msg if block_given?
|
21
|
-
msg.join("\n")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class Epass < Base
|
26
|
-
def initialize(argv)
|
27
|
-
@streaming = argv[-1] == '-'
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.summary
|
31
|
-
"Generate epasswords from individual database passwords"
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.help
|
35
|
-
help_message("epass [-]") do |msg|
|
36
|
-
msg << "With no arguments, interactively prompts for passwords and"
|
37
|
-
msg << " prints the corresponding epassword entry."
|
38
|
-
msg << ""
|
39
|
-
msg << "If the last argument is -, reads a newline-separated list"
|
40
|
-
msg << " of passwords from standard in and prints the corresponding "
|
41
|
-
msg << " epasswords to standard out."
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def main
|
46
|
-
@streaming ? streamed : interactive
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def streamed
|
52
|
-
$stdin.readlines.each do |line|
|
53
|
-
puts Bcdatabase.encrypt(line.chomp)
|
54
|
-
end
|
55
|
-
0
|
56
|
-
end
|
57
|
-
|
58
|
-
def interactive
|
59
|
-
begin
|
60
|
-
loop do
|
61
|
-
pass = HL.ask("Password (^C to end): ") do |q|
|
62
|
-
q.echo = false
|
63
|
-
end
|
64
|
-
puts " epassword: #{Bcdatabase.encrypt(pass)}"
|
65
|
-
end
|
66
|
-
rescue Interrupt
|
67
|
-
puts "\nQuit"
|
68
|
-
end
|
69
|
-
0
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class Encrypt < Base
|
74
|
-
def initialize(argv)
|
75
|
-
@input = argv.shift
|
76
|
-
@output = argv.shift
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.summary
|
80
|
-
"Encrypts all the password entries in a bcdatabase YAML file"
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.help
|
84
|
-
help_message("encrypt [inputfile [outputfile]]") do |msg|
|
85
|
-
msg << "Specifically, this command finds all the keys named 'password'"
|
86
|
-
msg << " in the input YAML and substitutes appropriate 'epassword'"
|
87
|
-
msg << " keys."
|
88
|
-
msg << ""
|
89
|
-
msg << "If inputfile is specified, the source will be that file."
|
90
|
-
msg << " If not, the source will be standard in."
|
91
|
-
msg << ""
|
92
|
-
msg << "If inputfile and outputfile are specified, the new file"
|
93
|
-
msg << " will be written to the output file. Otherwise the output"
|
94
|
-
msg << " will go to standard out. Input and output may be the same"
|
95
|
-
msg << " file."
|
96
|
-
msg << ""
|
97
|
-
msg << "You can't read from standard in and write to a file directly; "
|
98
|
-
msg << " use shell file redirection if you need to do that."
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def main
|
103
|
-
inio =
|
104
|
-
if @input
|
105
|
-
open(@input, "r")
|
106
|
-
else
|
107
|
-
$stdin
|
108
|
-
end
|
109
|
-
# try to preserve the order by replacing everything using regexes
|
110
|
-
contents = inio.read
|
111
|
-
contents.gsub!(/\bpassword:(\s*)(\S+)\s*?$/) { "epassword:#{$1}#{Bcdatabase.encrypt($2)}" }
|
112
|
-
outio =
|
113
|
-
if @output
|
114
|
-
open(@output, "w")
|
115
|
-
else
|
116
|
-
$stdout
|
117
|
-
end
|
118
|
-
outio.write(contents)
|
119
|
-
outio.close
|
120
|
-
0
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
class Help < Base
|
125
|
-
def initialize(argv)
|
126
|
-
@cmd = argv.shift
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.summary
|
130
|
-
"List commands or display help for one; e.g. #{UTILITY_NAME} help epass"
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.help
|
134
|
-
help_message "help [command name]"
|
135
|
-
end
|
136
|
-
|
137
|
-
def main
|
138
|
-
if @cmd
|
139
|
-
klass = Bcdatabase::Commands[@cmd]
|
140
|
-
if klass
|
141
|
-
msg = klass.respond_to?(:help) ? klass.help : klass.summary
|
142
|
-
$stderr.puts msg
|
143
|
-
else
|
144
|
-
$stderr.puts "Unknown command #{@cmd}"
|
145
|
-
return 1
|
146
|
-
end
|
147
|
-
else
|
148
|
-
$stderr.puts Bcdatabase::Commands.help
|
149
|
-
end
|
150
|
-
0
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
class GenKey < Base
|
155
|
-
def initialize(argv)
|
156
|
-
@stream = argv[-1] == '-'
|
157
|
-
end
|
158
|
-
|
159
|
-
def self.summary
|
160
|
-
"Generate a key for bcdatabase to use"
|
161
|
-
end
|
4
|
+
autoload :Encrypt, 'bcdatabase/commands/encrypt'
|
5
|
+
autoload :Epass, 'bcdatabase/commands/epass'
|
6
|
+
autoload :GenKey, 'bcdatabase/commands/gen_key'
|
162
7
|
|
163
|
-
|
164
|
-
|
165
|
-
msg << "By default, the key will be generated in "
|
166
|
-
msg << " #{Bcdatabase.pass_file}. If the last argument to this"
|
167
|
-
msg << " command is -, the key will be generated to standard out"
|
168
|
-
msg << " instead."
|
169
|
-
msg << ""
|
170
|
-
msg << "CAUTION: writing to #{Bcdatabase.pass_file} may overwrite"
|
171
|
-
msg << " an existing bcdatabase key. If that happens, you will"
|
172
|
-
msg << " need to reencrypt all the epasswords on this machine."
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def main
|
177
|
-
key = random_key(128)
|
178
|
-
outio =
|
179
|
-
if @stream
|
180
|
-
$stdout
|
181
|
-
else
|
182
|
-
file = Bcdatabase.pass_file
|
183
|
-
if File.exist?(file)
|
184
|
-
sure = HL.ask("This operation will overwrite the existing pass file.\n Are you sure you want to do that? ", %w{yes no}) do |q|
|
185
|
-
q.case = :down
|
186
|
-
end
|
187
|
-
unless sure == 'yes'
|
188
|
-
exit(0)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
open(file, "w")
|
192
|
-
end
|
193
|
-
outio.write key
|
194
|
-
outio.close
|
195
|
-
0
|
196
|
-
end
|
197
|
-
|
198
|
-
private
|
199
|
-
|
200
|
-
def random_key(length)
|
201
|
-
k = ""
|
202
|
-
# This is probably not going to work in ruby 1.9
|
203
|
-
until k.size == length; k << rand(126 - 32) + 32; end
|
204
|
-
k
|
205
|
-
end
|
206
|
-
end
|
8
|
+
class ForcedExit < StandardError
|
9
|
+
attr_reader :code
|
207
10
|
|
208
|
-
|
209
|
-
|
210
|
-
all_help = commands.collect { |c| [c.command_name, c.summary] }.sort_by { |p| p[0] }
|
211
|
-
max_name_length = all_help.collect { |a| a[0].size }.max
|
212
|
-
msg = Base.usage "<command> [args]\n"
|
213
|
-
msg << "Utility for bcdatabase #{Bcdatabase::VERSION}\n"
|
214
|
-
msg << "Commands:\n"
|
215
|
-
msg << all_help.collect { |name, help| " %#{max_name_length + 1}s %s" % [name, help] }.join("\n")
|
11
|
+
def initialize(code)
|
12
|
+
@code = code
|
216
13
|
end
|
217
|
-
|
218
|
-
# Lists all the commands
|
219
|
-
def commands
|
220
|
-
constants.reject { |cs| cs == "Base" }.collect { |cs| const_get(cs) }.select { |c| c.kind_of? Class }
|
221
|
-
end
|
222
|
-
|
223
|
-
# Locates the command class for a user-entered command name.
|
224
|
-
# Returns nil if the name is invalid.
|
225
|
-
def command(command_name)
|
226
|
-
begin
|
227
|
-
klassname = command_name.gsub('-', '_').camelize
|
228
|
-
Bcdatabase::Commands.const_get "#{klassname}"
|
229
|
-
rescue NameError
|
230
|
-
nil
|
231
|
-
end
|
232
|
-
end
|
233
|
-
alias :[] :command
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
class Class
|
238
|
-
def command_name
|
239
|
-
name.gsub(Bcdatabase::Commands.name + "::", '').underscore.gsub("_", '-')
|
240
14
|
end
|
241
15
|
end
|
data/lib/bcdatabase/version.rb
CHANGED
data/lib/bcdatabase.rb
CHANGED
@@ -2,9 +2,14 @@ require 'yaml'
|
|
2
2
|
require 'openssl'
|
3
3
|
require 'digest/sha2'
|
4
4
|
require 'base64'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
# Requiring just extract_options doesn't work on AS 2.3.
|
8
|
+
require 'active_support/core_ext/array'
|
5
9
|
|
6
10
|
module Bcdatabase
|
7
11
|
autoload :VERSION, 'bcdatabase/version'
|
12
|
+
autoload :CLI, 'bcdatabase/cli'
|
8
13
|
autoload :Commands, 'bcdatabase/commands'
|
9
14
|
|
10
15
|
DEFAULT_BASE_PATH = File.join('/', 'etc', 'nubic', 'db')
|
@@ -12,22 +17,51 @@ module Bcdatabase
|
|
12
17
|
CIPHER = 'aes-256-ecb'
|
13
18
|
|
14
19
|
class << self
|
15
|
-
|
16
|
-
|
20
|
+
##
|
21
|
+
# The main entry point for Bcdatabase.
|
22
|
+
#
|
23
|
+
# @overload load(options={})
|
24
|
+
# (See other alternative for option definitions.)
|
25
|
+
# @return [DatabaseConfigurations] a new instance using the
|
26
|
+
# default path.
|
27
|
+
# @overload load(path=nil, options={})
|
28
|
+
# @param [String,nil] path the directory to load from. If nil,
|
29
|
+
# will use the value in the environment variable
|
30
|
+
# `BCDATABASE_PATH`. If that's nil, too, it will use the
|
31
|
+
# default path.
|
32
|
+
# @param [Hash,nil] options additional options affecting the
|
33
|
+
# load behavior.
|
34
|
+
# @option options :transforms [Array<Symbol, #call>] ([]) Custom
|
35
|
+
# transforms. This can either be a symbol naming a
|
36
|
+
# {DatabaseConfigurations.BUILT_IN_TRANSFORMS built-in
|
37
|
+
# transform} or a callable which is the transform itself. A
|
38
|
+
# transform is a function that takes three arguments (the
|
39
|
+
# entry itself, the entry name, and the group name) and
|
40
|
+
# returns a new copy, modified as desired. It may also return
|
41
|
+
# nil to indicate that it doesn't wish to make any changes.
|
42
|
+
# @return [DatabaseConfigurations] a new instance reflecting
|
43
|
+
# the selected path.
|
44
|
+
def load(*args)
|
45
|
+
options = args.extract_options!
|
46
|
+
path ||= (args.first || base_path)
|
17
47
|
files = Dir.glob(File.join(path, "*.yml")) + Dir.glob(File.join(path, "*.yaml"))
|
18
|
-
DatabaseConfigurations.new(files)
|
48
|
+
DatabaseConfigurations.new(files, options[:transforms] || [])
|
19
49
|
end
|
20
50
|
|
51
|
+
##
|
52
|
+
# @private exposed for collaboration
|
21
53
|
def encrypt(s)
|
22
54
|
Base64.encode64(encipher(:encrypt, s)).strip
|
23
55
|
end
|
24
56
|
|
57
|
+
##
|
58
|
+
# @private exposed for collaboration
|
25
59
|
def decrypt(s)
|
26
60
|
encipher(:decrypt, Base64.decode64(s))
|
27
61
|
end
|
28
62
|
|
29
63
|
def pass_file
|
30
|
-
ENV["BCDATABASE_PASS"] || DEFAULT_PASS_FILE
|
64
|
+
Pathname.new(ENV["BCDATABASE_PASS"] || DEFAULT_PASS_FILE)
|
31
65
|
end
|
32
66
|
|
33
67
|
private
|
@@ -43,15 +77,30 @@ module Bcdatabase
|
|
43
77
|
end
|
44
78
|
|
45
79
|
def pass
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
80
|
+
@passes ||= { }
|
81
|
+
@passes[pass_file] ||=
|
82
|
+
begin
|
83
|
+
contents = read_pass_file
|
84
|
+
# This code may not work correctly on Ruby 1.9
|
85
|
+
if contents.size == 32
|
86
|
+
contents
|
87
|
+
else
|
88
|
+
Digest::SHA256.digest(contents)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_pass_file
|
94
|
+
unless pass_file.readable?
|
95
|
+
msg = [
|
96
|
+
"Bcdatabase keyfile #{pass_file} is not readable. Possible solutions:",
|
97
|
+
"* Use bcdatabase gen-key to generate a key",
|
98
|
+
"* Change the path by setting BCDATABASE_PASS in the environment",
|
99
|
+
"* Check the permissions on #{pass_file}"
|
100
|
+
].compact.join("\n")
|
101
|
+
raise Bcdatabase::Error, msg
|
54
102
|
end
|
103
|
+
pass_file.read
|
55
104
|
end
|
56
105
|
|
57
106
|
def base_path
|
@@ -59,8 +108,36 @@ module Bcdatabase
|
|
59
108
|
end
|
60
109
|
end
|
61
110
|
|
111
|
+
##
|
112
|
+
# The set of groups and entries returned by one call to {Bcdatabase.load}.
|
62
113
|
class DatabaseConfigurations
|
63
|
-
|
114
|
+
BUILT_IN_TRANSFORMS = {
|
115
|
+
:key_defaults => lambda { |entry, name, group|
|
116
|
+
{ 'username' => name, 'database' => name }.merge(entry)
|
117
|
+
},
|
118
|
+
:decrypt => lambda { |entry, name, group|
|
119
|
+
entry.merge({ 'password' => Bcdatabase.decrypt(entry['epassword']) }) if entry['epassword']
|
120
|
+
},
|
121
|
+
:datamapper => lambda { |entry, name, group|
|
122
|
+
entry.merge('adapter' => entry['datamapper_adapter']) if entry['datamapper_adapter']
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
##
|
127
|
+
# Creates a configuration from a set of YAML files.
|
128
|
+
#
|
129
|
+
# General use of the library should not use this method, but
|
130
|
+
# instead should use {Bcdatabase.load}.
|
131
|
+
def initialize(files, transforms=[])
|
132
|
+
@transforms = ([:key_defaults, :decrypt] + transforms).collect do |t|
|
133
|
+
case t
|
134
|
+
when Symbol
|
135
|
+
BUILT_IN_TRANSFORMS[t] or fail "No built-in transform named #{t.inspect}"
|
136
|
+
else
|
137
|
+
fail 'Transforms must by callable' unless t.respond_to?(:call)
|
138
|
+
t
|
139
|
+
end
|
140
|
+
end
|
64
141
|
@files = files
|
65
142
|
@map = { }
|
66
143
|
files.each do |filename|
|
@@ -69,10 +146,18 @@ module Bcdatabase
|
|
69
146
|
end
|
70
147
|
end
|
71
148
|
|
149
|
+
##
|
150
|
+
# @return [Hash] the entry for the given group and name after all
|
151
|
+
# transformation is complete.
|
72
152
|
def [](groupname, dbname)
|
73
153
|
create_entry(groupname.to_s, dbname.to_s)
|
74
154
|
end
|
75
155
|
|
156
|
+
##
|
157
|
+
# This method implements the Rails database.yml integration
|
158
|
+
# described in full in the {file:README.markdown}.
|
159
|
+
#
|
160
|
+
# @return [String] a YAMLized view of a configuration entry.
|
76
161
|
def method_missing(name, *args)
|
77
162
|
groupname = (args[0] or raise "Database configuration group not specified for #{name}")
|
78
163
|
dbname = (args[1] or raise "Database entry name not specified for #{name}")
|
@@ -94,16 +179,16 @@ module Bcdatabase
|
|
94
179
|
|
95
180
|
def create_entry(groupname, dbname)
|
96
181
|
group = @map[groupname] or raise Error.new("No database configuration group named #{groupname.inspect} found. (Found #{@map.keys.inspect}.)")
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
182
|
+
unless group.has_key?(dbname)
|
183
|
+
raise Error.new("No database entry for #{dbname.inspect} in #{groupname}.")
|
184
|
+
end
|
185
|
+
db = group[dbname] || {}
|
186
|
+
base = (group['defaults'] || {}).
|
187
|
+
merge(group['default'] || {}).
|
188
|
+
merge(db)
|
189
|
+
@transforms.inject(base) do |result, transform|
|
190
|
+
transform.call(result, dbname, groupname) || result
|
105
191
|
end
|
106
|
-
merged
|
107
192
|
end
|
108
193
|
|
109
194
|
def unseparated_yaml(arg)
|
@@ -111,5 +196,5 @@ module Bcdatabase
|
|
111
196
|
end
|
112
197
|
end
|
113
198
|
|
114
|
-
class Error <
|
199
|
+
class Error < StandardError; end
|
115
200
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bcdatabase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.6
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Rhett Sutphin
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-08-30 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -63,24 +63,72 @@ dependencies:
|
|
63
63
|
type: :runtime
|
64
64
|
version_requirements: *id003
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
66
|
+
name: thor
|
67
67
|
prerelease: false
|
68
68
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
69
|
none: false
|
70
70
|
requirements:
|
71
71
|
- - ~>
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
hash:
|
73
|
+
hash: 43
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
- 14
|
77
|
+
- 6
|
78
|
+
version: 0.14.6
|
79
|
+
type: :runtime
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: bundler
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 9
|
74
90
|
segments:
|
75
91
|
- 1
|
92
|
+
- 0
|
93
|
+
- 15
|
94
|
+
version: 1.0.15
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
prerelease: false
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 63
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
- 9
|
76
109
|
- 2
|
77
|
-
version:
|
110
|
+
version: 0.9.2
|
78
111
|
type: :development
|
79
|
-
version_requirements: *
|
112
|
+
version_requirements: *id006
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rspec
|
115
|
+
prerelease: false
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ~>
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 15
|
122
|
+
segments:
|
123
|
+
- 2
|
124
|
+
- 6
|
125
|
+
version: "2.6"
|
126
|
+
type: :development
|
127
|
+
version_requirements: *id007
|
80
128
|
- !ruby/object:Gem::Dependency
|
81
129
|
name: ci_reporter
|
82
130
|
prerelease: false
|
83
|
-
requirement: &
|
131
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
84
132
|
none: false
|
85
133
|
requirements:
|
86
134
|
- - ~>
|
@@ -91,8 +139,24 @@ dependencies:
|
|
91
139
|
- 6
|
92
140
|
version: "1.6"
|
93
141
|
type: :development
|
94
|
-
version_requirements: *
|
95
|
-
|
142
|
+
version_requirements: *id008
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
name: yard
|
145
|
+
prerelease: false
|
146
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ~>
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
hash: 7
|
152
|
+
segments:
|
153
|
+
- 0
|
154
|
+
- 7
|
155
|
+
- 2
|
156
|
+
version: 0.7.2
|
157
|
+
type: :development
|
158
|
+
version_requirements: *id009
|
159
|
+
description: bcdatabase is a tool for storing passwords and other configuration information outside of your application source tree.
|
96
160
|
email: rhett@detailedbalance.net
|
97
161
|
executables:
|
98
162
|
- bcdatabase
|
@@ -104,12 +168,17 @@ files:
|
|
104
168
|
- CHANGELOG.markdown
|
105
169
|
- LICENSE
|
106
170
|
- README.markdown
|
171
|
+
- bcdatabase.gemspec
|
107
172
|
- bin/bcdatabase
|
173
|
+
- lib/bcdatabase/cli.rb
|
174
|
+
- lib/bcdatabase/commands/encrypt.rb
|
175
|
+
- lib/bcdatabase/commands/epass.rb
|
176
|
+
- lib/bcdatabase/commands/gen_key.rb
|
108
177
|
- lib/bcdatabase/commands.rb
|
109
178
|
- lib/bcdatabase/version.rb
|
110
179
|
- lib/bcdatabase.rb
|
111
180
|
has_rdoc: true
|
112
|
-
homepage: http://github.com/
|
181
|
+
homepage: http://github.com/NUBIC/bcdatabase
|
113
182
|
licenses: []
|
114
183
|
|
115
184
|
post_install_message:
|