bitca 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 526308b797c2fa7fd78cf53134001ffe88915e1a
4
+ data.tar.gz: c347aea101daf5ad97122ef78598ff9be053e7dd
5
+ SHA512:
6
+ metadata.gz: 9e828ed837fa4f45ad59cbb229c413d30c006a010c9d7ddb091e1b50f3f6b2312463a4215f80f09605a115d18df675c4732859b55c1e75b7253295119e45c7c5
7
+ data.tar.gz: 2524b029adc60d4d7be33565b99e29c5f532611f7c9776b2be20c3552e9231c211d5b45228fe90c1ed2bba15986cf691854255e233e2e31342f74ade2effba71
@@ -0,0 +1,38 @@
1
+ # ignore everything in log and pids directory, but keep it
2
+ pid/*
3
+ !pid/.gitignore
4
+ log/*
5
+ !log/.gitignore
6
+
7
+ # temporary dir
8
+ tmp/
9
+
10
+ # config
11
+ config/config.yml
12
+ config/original_config.yml
13
+
14
+ # JetBrains RubyMine files
15
+ .idea
16
+
17
+ # vim temporary files
18
+ *.swp
19
+ *.swo
20
+
21
+ # gem related
22
+ *.gem
23
+ *.rbc
24
+ .bundle
25
+ .config
26
+ .yardoc
27
+ Gemfile.lock
28
+ InstalledFiles
29
+ _yardoc
30
+ coverage
31
+ doc/
32
+ lib/bundler/man
33
+ pkg
34
+ rdoc
35
+ spec/reports
36
+ test/tmp
37
+ test/version_tmp
38
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,190 @@
1
+ Evia Project - bitca
2
+ Copyright 2013 Relbit Ltd.
3
+
4
+ Unless explicitly noted otherwise, all files under this directory are
5
+ licensed under the Apache License, Version 2.0 (the "License"); you may
6
+ not use this product except in compliance with the License attached
7
+ below.
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
14
+
15
+ Apache License
16
+ Version 2.0, January 2004
17
+ http://www.apache.org/licenses/
18
+
19
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
20
+
21
+ 1. Definitions.
22
+
23
+ "License" shall mean the terms and conditions for use, reproduction,
24
+ and distribution as defined by Sections 1 through 9 of this document.
25
+
26
+ "Licensor" shall mean the copyright owner or entity authorized by
27
+ the copyright owner that is granting the License.
28
+
29
+ "Legal Entity" shall mean the union of the acting entity and all
30
+ other entities that control, are controlled by, or are under common
31
+ control with that entity. For the purposes of this definition,
32
+ "control" means (i) the power, direct or indirect, to cause the
33
+ direction or management of such entity, whether by contract or
34
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
35
+ outstanding shares, or (iii) beneficial ownership of such entity.
36
+
37
+ "You" (or "Your") shall mean an individual or Legal Entity
38
+ exercising permissions granted by this License.
39
+
40
+ "Source" form shall mean the preferred form for making modifications,
41
+ including but not limited to software source code, documentation
42
+ source, and configuration files.
43
+
44
+ "Object" form shall mean any form resulting from mechanical
45
+ transformation or translation of a Source form, including but
46
+ not limited to compiled object code, generated documentation,
47
+ and conversions to other media types.
48
+
49
+ "Work" shall mean the work of authorship, whether in Source or
50
+ Object form, made available under the License, as indicated by a
51
+ copyright notice that is included in or attached to the work
52
+ (an example is provided in the Appendix below).
53
+
54
+ "Derivative Works" shall mean any work, whether in Source or Object
55
+ form, that is based on (or derived from) the Work and for which the
56
+ editorial revisions, annotations, elaborations, or other modifications
57
+ represent, as a whole, an original work of authorship. For the purposes
58
+ of this License, Derivative Works shall not include works that remain
59
+ separable from, or merely link (or bind by name) to the interfaces of,
60
+ the Work and Derivative Works thereof.
61
+
62
+ "Contribution" shall mean any work of authorship, including
63
+ the original version of the Work and any modifications or additions
64
+ to that Work or Derivative Works thereof, that is intentionally
65
+ submitted to Licensor for inclusion in the Work by the copyright owner
66
+ or by an individual or Legal Entity authorized to submit on behalf of
67
+ the copyright owner. For the purposes of this definition, "submitted"
68
+ means any form of electronic, verbal, or written communication sent
69
+ to the Licensor or its representatives, including but not limited to
70
+ communication on electronic mailing lists, source code control systems,
71
+ and issue tracking systems that are managed by, or on behalf of, the
72
+ Licensor for the purpose of discussing and improving the Work, but
73
+ excluding communication that is conspicuously marked or otherwise
74
+ designated in writing by the copyright owner as "Not a Contribution."
75
+
76
+ "Contributor" shall mean Licensor and any individual or Legal Entity
77
+ on behalf of whom a Contribution has been received by Licensor and
78
+ subsequently incorporated within the Work.
79
+
80
+ 2. Grant of Copyright License. Subject to the terms and conditions of
81
+ this License, each Contributor hereby grants to You a perpetual,
82
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
83
+ copyright license to reproduce, prepare Derivative Works of,
84
+ publicly display, publicly perform, sublicense, and distribute the
85
+ Work and such Derivative Works in Source or Object form.
86
+
87
+ 3. Grant of Patent License. Subject to the terms and conditions of
88
+ this License, each Contributor hereby grants to You a perpetual,
89
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
90
+ (except as stated in this section) patent license to make, have made,
91
+ use, offer to sell, sell, import, and otherwise transfer the Work,
92
+ where such license applies only to those patent claims licensable
93
+ by such Contributor that are necessarily infringed by their
94
+ Contribution(s) alone or by combination of their Contribution(s)
95
+ with the Work to which such Contribution(s) was submitted. If You
96
+ institute patent litigation against any entity (including a
97
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
98
+ or a Contribution incorporated within the Work constitutes direct
99
+ or contributory patent infringement, then any patent licenses
100
+ granted to You under this License for that Work shall terminate
101
+ as of the date such litigation is filed.
102
+
103
+ 4. Redistribution. You may reproduce and distribute copies of the
104
+ Work or Derivative Works thereof in any medium, with or without
105
+ modifications, and in Source or Object form, provided that You
106
+ meet the following conditions:
107
+
108
+ (a) You must give any other recipients of the Work or
109
+ Derivative Works a copy of this License; and
110
+
111
+ (b) You must cause any modified files to carry prominent notices
112
+ stating that You changed the files; and
113
+
114
+ (c) You must retain, in the Source form of any Derivative Works
115
+ that You distribute, all copyright, patent, trademark, and
116
+ attribution notices from the Source form of the Work,
117
+ excluding those notices that do not pertain to any part of
118
+ the Derivative Works; and
119
+
120
+ (d) If the Work includes a "NOTICE" text file as part of its
121
+ distribution, then any Derivative Works that You distribute must
122
+ include a readable copy of the attribution notices contained
123
+ within such NOTICE file, excluding those notices that do not
124
+ pertain to any part of the Derivative Works, in at least one
125
+ of the following places: within a NOTICE text file distributed
126
+ as part of the Derivative Works; within the Source form or
127
+ documentation, if provided along with the Derivative Works; or,
128
+ within a display generated by the Derivative Works, if and
129
+ wherever such third-party notices normally appear. The contents
130
+ of the NOTICE file are for informational purposes only and
131
+ do not modify the License. You may add Your own attribution
132
+ notices within Derivative Works that You distribute, alongside
133
+ or as an addendum to the NOTICE text from the Work, provided
134
+ that such additional attribution notices cannot be construed
135
+ as modifying the License.
136
+
137
+ You may add Your own copyright statement to Your modifications and
138
+ may provide additional or different license terms and conditions
139
+ for use, reproduction, or distribution of Your modifications, or
140
+ for any such Derivative Works as a whole, provided Your use,
141
+ reproduction, and distribution of the Work otherwise complies with
142
+ the conditions stated in this License.
143
+
144
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
145
+ any Contribution intentionally submitted for inclusion in the Work
146
+ by You to the Licensor shall be under the terms and conditions of
147
+ this License, without any additional terms or conditions.
148
+ Notwithstanding the above, nothing herein shall supersede or modify
149
+ the terms of any separate license agreement you may have executed
150
+ with Licensor regarding such Contributions.
151
+
152
+ 6. Trademarks. This License does not grant permission to use the trade
153
+ names, trademarks, service marks, or product names of the Licensor,
154
+ except as required for reasonable and customary use in describing the
155
+ origin of the Work and reproducing the content of the NOTICE file.
156
+
157
+ 7. Disclaimer of Warranty. Unless required by applicable law or
158
+ agreed to in writing, Licensor provides the Work (and each
159
+ Contributor provides its Contributions) on an "AS IS" BASIS,
160
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
161
+ implied, including, without limitation, any warranties or conditions
162
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
163
+ PARTICULAR PURPOSE. You are solely responsible for determining the
164
+ appropriateness of using or redistributing the Work and assume any
165
+ risks associated with Your exercise of permissions under this License.
166
+
167
+ 8. Limitation of Liability. In no event and under no legal theory,
168
+ whether in tort (including negligence), contract, or otherwise,
169
+ unless required by applicable law (such as deliberate and grossly
170
+ negligent acts) or agreed to in writing, shall any Contributor be
171
+ liable to You for damages, including any direct, indirect, special,
172
+ incidental, or consequential damages of any character arising as a
173
+ result of this License or out of the use or inability to use the
174
+ Work (including but not limited to damages for loss of goodwill,
175
+ work stoppage, computer failure or malfunction, or any and all
176
+ other commercial damages or losses), even if such Contributor
177
+ has been advised of the possibility of such damages.
178
+
179
+ 9. Accepting Warranty or Additional Liability. While redistributing
180
+ the Work or Derivative Works thereof, You may choose to offer,
181
+ and charge a fee for, acceptance of support, warranty, indemnity,
182
+ or other liability obligations and/or rights consistent with this
183
+ License. However, in accepting such obligations, You may act only
184
+ on Your own behalf and on Your sole responsibility, not on behalf
185
+ of any other Contributor, and only if You agree to indemnify,
186
+ defend, and hold each Contributor harmless for any liability
187
+ incurred by, or claims asserted against, such Contributor by reason
188
+ of your accepting any such warranty or additional liability.
189
+
190
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1,29 @@
1
+ # Bitca
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'bitca'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install bitca
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,18 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ # Monkey patch Bundler gem_helper so we release to our gem server instead of rubygems.org
4
+ module Bundler
5
+ class GemHelper
6
+ def rubygem_push(path)
7
+ gem_server_url = 'http://gem.int.prg.relbit.com:80/'
8
+ sh("gem inabox '#{path}' --host #{gem_server_url}")
9
+ Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_server_url}"
10
+ end
11
+ def perform_git_push(options = '')
12
+ puts "not pushing for now ... "
13
+ cmd = "git push #{options}"
14
+ out, code = sh_with_code(cmd)
15
+ raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0
16
+ end
17
+ end
18
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.2
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ APP_DIR = File.expand_path("#{File.dirname(__FILE__)}/../")
4
+ require APP_DIR + "/lib/bitca"
5
+
6
+ options = {
7
+ :config_path => "/etc/bitca.yml"
8
+ }
9
+
10
+ optparse = OptionParser.new do |opts|
11
+ opts.banner = "Usage: bitca [options]"
12
+ opts.define_head "Main, version #pojebse"
13
+ opts.separator "\nOptions:"
14
+
15
+ opts.on('-c', '--config FILE', "Path to config file, defaults to #{options[:config_path]}") do |config_path|
16
+ options[:config_path] = File.expand_path("#{Dir.getwd}/#{config_path}")
17
+ end
18
+
19
+ opts.on('-i', '--init', "Initialize the CA and pwdgen for the first time") do |init|
20
+ options[:init] = init
21
+ end
22
+
23
+ opts.on('-g', "--generate HOSTNAME", "Generate key and password for HOSTNAME (unless --keys-only or --pwd-only was given)") do |hostname|
24
+ options[:hostname] = hostname
25
+ options[:generate] = true
26
+ end
27
+
28
+ opts.on('-s', "--show HOSTNAME", "Show key and password for HOSTNAME (unless --keys-only or --pwd-only was given)") do |hostname|
29
+ options[:hostname] = hostname
30
+ options[:generate] = false
31
+ end
32
+
33
+ opts.on('-f', "--force", "Overwrite existing keys/pwd") do |force|
34
+ options[:force] = force
35
+ end
36
+
37
+ opts.on('-k', "--keys-only", "Generate keys only") do |keys_only|
38
+ options[:keys_only] = keys_only
39
+ end
40
+
41
+ opts.on('-p', "--pwd-only", "Generate pwd only") do |pwd_only|
42
+ options[:pwd_only] = pwd_only
43
+ end
44
+
45
+ opts.on('-m', "--print-sample-config", "Prints sample config") do |print_sample_config|
46
+ options[:print_sample_config] = print_sample_config
47
+ end
48
+
49
+ opts.on("-v", "--version", "Prints version") do
50
+ puts "Bitca, version #{Bitca::VERSION}"
51
+ exit
52
+ end
53
+
54
+ help = Proc.new do
55
+ puts opts
56
+ puts
57
+ puts 'To initiate a new CA:'
58
+ puts 'bitca --init'
59
+ puts
60
+ puts 'To generate bundle of HTTP basic password and RSA key signed by CA:'
61
+ puts 'bitca --generate example.com'
62
+ puts
63
+ puts 'bitca --generate example.com --key-only'
64
+ puts 'bitca --generate example.com --pwd-only'
65
+
66
+ exit
67
+ end
68
+
69
+ opts.on_tail('-h','--help', 'Show this message', &help)
70
+ help.call if ARGV.empty?
71
+ end
72
+
73
+ begin
74
+ optparse.parse!
75
+ raise "Don't know what to do, because --pwd-only and --key-only were given at the same time" if options[:pwd_only] && options[:key_only]
76
+ rescue => e
77
+ STDERR.puts(e.message)
78
+ exit(1)
79
+ end
80
+
81
+ begin
82
+ if options[:print_sample_config]
83
+ Bitca::Main.print_sample_config
84
+ exit
85
+ end
86
+
87
+ bitca = Bitca::Main.new options[:config_path]
88
+
89
+ if options[:init]
90
+ bitca.init
91
+ end
92
+
93
+ unless options[:hostname].nil?
94
+ bitca.generate(options[:hostname], options) if options[:generate]
95
+ STDOUT.puts JSON.pretty_generate(bitca.show(options[:hostname], options))
96
+ end
97
+ rescue Bitca::ConfigMissingError => e
98
+ STDERR.puts(e.message)
99
+ Bitca::Main.print_sample_config
100
+ exit
101
+ rescue => e
102
+ STDERR.puts("Main operation failed: #{e.message}")
103
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bitca/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "bitca"
8
+ gem.version = Bitca::VERSION
9
+ gem.authors = ["snajpa"]
10
+ gem.email = ["pavel.snajdr@relbit.com"]
11
+ gem.description = "Bitca"
12
+ gem.summary = "Bitca"
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_development_dependency 'geminabox', '~>0.10.1'
20
+ gem.add_dependency 'rake', '~>10.1.0'
21
+ gem.add_dependency 'json', '~>1.8.0'
22
+ end
data/ca.crt ADDED
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDiDCCAnACCQCiN90NTa66gjANBgkqhkiG9w0BAQQFADCBhTEWMBQGA1UEChMN
3
+ UmVsYml0IHMuci5vLjELMAkGA1UECxMCTkExHDAaBgkqhkiG9w0BCQEWDWNhQHJl
4
+ bGJpdC5jb20xEzARBgNVBAcTCkJyYXRpc2xhdmExETAPBgNVBAgTCFNsb3Zha2lh
5
+ MQswCQYDVQQGEwJTSzELMAkGA1UEAxMCY2EwHhcNMTIxMTEyMTYxNTA4WhcNMjIx
6
+ MTEwMTYxNTA4WjCBhTEWMBQGA1UEChMNUmVsYml0IHMuci5vLjELMAkGA1UECxMC
7
+ TkExHDAaBgkqhkiG9w0BCQEWDWNhQHJlbGJpdC5jb20xEzARBgNVBAcTCkJyYXRp
8
+ c2xhdmExETAPBgNVBAgTCFNsb3Zha2lhMQswCQYDVQQGEwJTSzELMAkGA1UEAxMC
9
+ Y2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz2K29bvlK5gDqRj0M
10
+ JPz8AlUKJolK2AgZLNOZVzk+LL39S4yZeNzGygv223B636BbfBelRiyc7oYeV6kJ
11
+ QKCyXoDx2i5wGuynHteQ2X2n7LeuxO+glfUn0XZD5UHuxLk8nYqlcalLDRdehDQ3
12
+ jQSM43fu6eGDZwYtXqdORFZf2cSMpoffGmbZHZhus9wic5hKwy8FmWppF0tRn556
13
+ EvVkMLCwqw9/iXGKiriiNt+ePhEUnjAGEXw5LMXWDEzjHS7mS1UUvdOiiC50ontt
14
+ 8a010ClRpEDNG2Sg/Tveao+j7j2u3OjL/6DSREQtV2Z4nYJyMmRy53nVSomTBA6l
15
+ GfeDAgMBAAEwDQYJKoZIhvcNAQEEBQADggEBAHJ4IqLKPndVF30/DCY/tfOZoK8z
16
+ z9e5jq/SFdAoO16oP5nBVdG8D1emiRgnE0OMFODk39L8FDFp5q9eFM3e3iqdzml0
17
+ l8fCiN856Jp+gbdFTyu/NqccpEBOmUf5I9zKPukj1pcxGzpri1snfRgAN5GNBdiW
18
+ qbYQ+t9lvuT/w8Fu/mxrYxui+6u67+v81z3mFJLfiCqWa/H8Z7ErKb6Z5GtTOrxA
19
+ t+ttzU/GHSncOB1GZD832wDU3jKi0CvNm2nQ8IYwjI/JDTM67EF/RC/Sn1fL7xY4
20
+ I9hAMwrXuke4Hdh0kSem0MoLrtmNfmTIC4WgekmUv1AGa9aTVTk9fkUsUnA=
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,10 @@
1
+ path: /tmp/uzasnanovaCA
2
+ pwdsize: 40
3
+ keysize: 2048
4
+ days: 3650
5
+ countryName: SK
6
+ stateOrProvinceName: Slovakia
7
+ localityName: Bratislava
8
+ organizationName: Relbit s.r.o.
9
+ organizationalUnitName: NA
10
+ emailAddress: ca@relbit.com
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'erb'
4
+ require 'optparse'
5
+ require 'yaml'
6
+
7
+ $:.unshift File.dirname(__FILE__)
8
+
9
+ require 'bitca/main'
10
+ require 'bitca/certificate_authority'
11
+ require 'bitca/pwdgen'
12
+ require 'bitca/version'
13
+
14
+ module Bitca
15
+
16
+ end
@@ -0,0 +1,192 @@
1
+ module Bitca
2
+ class CertificateAuthorityError < StandardError; end
3
+
4
+ class CertificateAuthority
5
+ def initialize(rootpath='.',keysize=2048,days=3650)
6
+ @rootpath = rootpath
7
+ @capath = "#@rootpath/ca"
8
+ @ca_crt = "#@capath/ca.crt"
9
+ @ca_key = "#@capath/ca.key"
10
+ @keyspath = "#@rootpath/keys"
11
+ @cfgpath = "#@rootpath/cfg"
12
+ @cfgtemplate = "#@rootpath/cfg.erb"
13
+ @keysize = keysize
14
+ @days = days
15
+ end
16
+
17
+ def list(type = :key)
18
+ items = []
19
+
20
+ Dir.foreach(@keyspath) do |f|
21
+ next unless f =~ /\.#{type}$/
22
+ items << f.gsub(/\.#{type}$/, '')
23
+ end
24
+
25
+ items
26
+ end
27
+
28
+ def ca_exists?
29
+ File.exist?(@ca_crt) and File.exist?(@ca_key)
30
+ end
31
+
32
+ def req_exists?(cn)
33
+ File.exist?("#@keyspath/#{cn}.csr")
34
+ end
35
+
36
+ def key_exists?(cn)
37
+ File.exist?("#@keyspath/#{cn}.key")
38
+ end
39
+
40
+ def crt_exists?(cn)
41
+ File.exist?("#@keyspath/#{cn}.crt")
42
+ end
43
+
44
+ def genkey(cn)
45
+ openssl :genrsa, "-out #@keyspath/#{cn}.key #@keysize"
46
+ end
47
+
48
+ def genreq(cn)
49
+ gencfg cn
50
+ openssl :req, "-new -key #@keyspath/#{cn}.key -out #@keyspath/#{cn}.csr -batch -config #@cfgpath/#{cn}"
51
+ end
52
+
53
+ def sign(cn)
54
+ openssl :x509, "-req -in #@keyspath/#{cn}.csr -CA #@ca_crt -CAkey #@ca_key -CAcreateserial -out #@keyspath/#{cn}.crt -days #@days"
55
+ end
56
+
57
+ def get_bundle(cn)
58
+ list = {}
59
+
60
+ { :ca_crt => @ca_crt,
61
+ :cfg => "#@cfgpath/#{cn}",
62
+ :crt => "#@keyspath/#{cn}.crt",
63
+ :csr => "#@keyspath/#{cn}.csr",
64
+ :key => "#@keyspath/#{cn}.key"}.each do |type, f|
65
+ list[type] = File.read(f) if File.exist?(f)
66
+ end
67
+
68
+ list
69
+ end
70
+
71
+ def get_files(cn)
72
+ list = {}
73
+
74
+ { :cfg => "#@cfgpath/#{cn}",
75
+ :crt => "#@keyspath/#{cn}.crt",
76
+ :csr => "#@keyspath/#{cn}.csr",
77
+ :key => "#@keyspath/#{cn}.key"}.each do |type, f|
78
+ list[type] = f if File.exist?(f)
79
+ end
80
+
81
+ list
82
+ end
83
+
84
+ def remove(cn)
85
+ return false unless key_exists?(cn)
86
+
87
+ get_files(cn).each do |type, f|
88
+ File.delete(f)
89
+ end
90
+
91
+ true
92
+ end
93
+
94
+ def genca (params = {})
95
+ return false if ca_exists?
96
+
97
+ gencfg_template params
98
+ gencfg "ca"
99
+
100
+ openssl :genrsa, "-out #@ca_key #@keysize"
101
+ openssl :req, "-x509 -new -days #@days -nodes -out #@ca_crt -key #@ca_key -batch -config #@cfgpath/ca"
102
+
103
+ File.chmod(0600, @ca_key, @ca_crt)
104
+
105
+ true
106
+ end
107
+
108
+ private
109
+ def mkdirs
110
+ mask = 0700
111
+ Dir.mkdir(@rootpath, mask) unless File.directory?(@rootpath)
112
+ Dir.mkdir(@capath, mask) unless File.directory?(@capath)
113
+ Dir.mkdir(@keyspath, mask) unless File.directory?(@keyspath)
114
+ Dir.mkdir(@cfgpath, mask) unless File.directory?(@cfgpath)
115
+ end
116
+
117
+ def gencfg(cn)
118
+ mkdirs
119
+
120
+ commonName = cn
121
+
122
+ erb = ERB.new(File.read(@cfgtemplate))
123
+
124
+ file = File.new("#@cfgpath/#{cn}", "w")
125
+ file.write(erb.result(binding))
126
+ file.close
127
+ end
128
+
129
+ def gencfg_template(params = {})
130
+ mkdirs
131
+
132
+ vars = {}
133
+
134
+ %w( countryName
135
+ stateOrProvinceName
136
+ localityName
137
+ organizationName
138
+ organizationalUnitName
139
+ emailAddress ).each do |v|
140
+ unless params[v.to_sym].nil?
141
+ vars[v.to_sym] = params[v.to_sym]
142
+ else
143
+ vars[v.to_sym] = "NA"
144
+ end
145
+ end
146
+
147
+ cfg = %q{
148
+ [ req ]
149
+ default_bits = <%= @keysize %>
150
+ default_keyfile = key.pem
151
+ default_md = md5
152
+ string_mask = nombstr
153
+ distinguished_name = req_distinguished_name
154
+
155
+ [ req_distinguished_name ]
156
+ 0.organizationName = Organization Name (company)
157
+ organizationalUnitName = Organizational Unit Name (department, division)
158
+ emailAddress = Email Address
159
+ emailAddress_max = 40
160
+ localityName = Locality Name (city, district)
161
+ stateOrProvinceName = State or Province Name (full name)
162
+ countryName = Country Name (2 letter code)
163
+ countryName_min = 2
164
+ countryName_max = 2
165
+ commonName = Common Name (hostname, IP, or your name)
166
+ commonName_max = 64
167
+
168
+ countryName_default = <%= vars[:countryName] %>
169
+ stateOrProvinceName_default = <%= vars[:stateOrProvinceName] %>
170
+ localityName_default = <%= vars[:localityName] %>
171
+ 0.organizationName_default = <%= vars[:organizationName] %>
172
+ organizationalUnitName_default = <%= vars[:organizationalUnitName] %>
173
+ commonName_default = <%%= commonName %>
174
+ emailAddress_default = <%= vars[:emailAddress] %>
175
+ }.gsub(/^\s+/, '')
176
+
177
+ erb = ERB.new(cfg)
178
+
179
+ file = File.new(@cfgtemplate, "w")
180
+ file.write(erb.result(binding))
181
+ file.close
182
+ end
183
+
184
+ def openssl(command, params)
185
+ `openssl #{command.to_s} #{params} 2>&1 >/dev/null`
186
+
187
+ raise CertificateAuthorityError, "openssl call error: #{cmd}" unless $?.exitstatus == 0
188
+
189
+ true
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,82 @@
1
+ module Bitca
2
+
3
+ class ConfigMissingError < StandardError; end
4
+
5
+ class Main
6
+
7
+ def self.print_sample_config
8
+ STDOUT.puts(File.read("#{APP_DIR}/config/sample_config.yml"))
9
+ end
10
+
11
+ def initialize(config_path)
12
+ raise ConfigMissingError, "Config '#{File.expand_path(config_path)}' does not exist" unless File.exists?(config_path)
13
+ @config = symbolize_keys(YAML.load_file(config_path))
14
+ @ca = CertificateAuthority.new(@config[:path], @config[:keysize], @config[:days])
15
+ @pwdgen = Pwdgen.new(@config[:path], @config[:pwdsize])
16
+ end
17
+
18
+ def init
19
+ unless @ca.ca_exists?
20
+ @ca.genca @config
21
+ @pwdgen.init
22
+ else
23
+ raise "CA already initialized"
24
+ end
25
+ end
26
+
27
+ def generate(hostname, options)
28
+ raise "CA not initialized" unless @ca.ca_exists?
29
+
30
+ unless options[:pwd_only]
31
+ if @ca.list.include?(hostname) && !options[:force]
32
+ raise "Keys for #{hostname} already exist"
33
+ else
34
+ @ca.genkey hostname
35
+ @ca.genreq hostname
36
+ @ca.sign hostname
37
+ end
38
+ end
39
+
40
+ unless options[:keys_only]
41
+ if @pwdgen.list.include?(hostname) && !options[:force]
42
+ raise "Password for #{hostname} already exists"
43
+ else
44
+ @pwdgen.genpwd hostname
45
+ end
46
+ end
47
+ end
48
+
49
+ def show(hostname, options)
50
+ raise "CA not initialized" unless @ca.ca_exists?
51
+
52
+ ret = {}
53
+
54
+ unless options[:pwd_only]
55
+ if @ca.list.include?(hostname)
56
+ ret.merge!(@ca.get_bundle(hostname))
57
+ else
58
+ raise "Keys for #{hostname} do not exist"
59
+ end
60
+ end
61
+
62
+ unless options[:keys_only]
63
+ if @pwdgen.list.include?(hostname)
64
+ ret.merge!({:password => @pwdgen.getpwd(hostname)})
65
+ else
66
+ raise "Password for #{hostname} does not exist"
67
+ end
68
+ end
69
+
70
+ ret
71
+ end
72
+
73
+ private
74
+ def symbolize_keys(hash)
75
+ new = {}
76
+ hash.each { |k, v| new[k.to_sym] = v.class == Hash ? self.symbolize_keys(v) : v }
77
+ new
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,49 @@
1
+ module Bitca
2
+ class Pwdgen
3
+ def initialize(rootpath = '.', pwdsize = 40)
4
+ @pwdsize = pwdsize
5
+ @rootpath = rootpath
6
+ @pwdpath = "#{rootpath}/pwd"
7
+ end
8
+
9
+ def init
10
+ Dir.mkdir(@pwdpath, 0700) unless File.directory?(@pwdpath)
11
+ end
12
+
13
+ def list
14
+ items = []
15
+
16
+ Dir.foreach(@pwdpath) do |f|
17
+ next unless f =~ /\.pwd$/
18
+ items << f.gsub(/\.pwd$/, '')
19
+ end
20
+
21
+ items
22
+ end
23
+
24
+ def pwd_exists?(cn)
25
+ File.exist?("#{@pwdpath}/#{cn}.pwd")
26
+ end
27
+
28
+ def genpwd(cn)
29
+ chars = (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a) + %w(i I o O 1 l 0)
30
+ pwd = (1..@pwdsize).collect{|a| chars[rand(chars.size)] }.join
31
+
32
+ f = File.new("#{@pwdpath}/#{cn}.pwd", "w")
33
+ f.puts pwd
34
+ f.close
35
+
36
+ pwd
37
+ end
38
+
39
+ def getpwd(cn)
40
+ return false unless pwd_exists?(cn)
41
+ File.read("#{@pwdpath}/#{cn}.pwd").gsub /\n/, ''
42
+ end
43
+
44
+ def remove(cn)
45
+ return false unless pwd_exists?(cn)
46
+ File.delete("#{@pwdpath}/#{cn}.pwd")
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Bitca
2
+ VERSION = '2.0.2'
3
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitca
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.2
5
+ platform: ruby
6
+ authors:
7
+ - snajpa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: geminabox
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.1
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 10.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 10.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.8.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.0
55
+ description: Bitca
56
+ email:
57
+ - pavel.snajdr@relbit.com
58
+ executables:
59
+ - bitca
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - VERSION
69
+ - bin/bitca
70
+ - bitca.gemspec
71
+ - ca.crt
72
+ - config/sample_config.yml
73
+ - lib/bitca.rb
74
+ - lib/bitca/certificate_authority.rb
75
+ - lib/bitca/main.rb
76
+ - lib/bitca/pwdgen.rb
77
+ - lib/bitca/version.rb
78
+ homepage: ''
79
+ licenses: []
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.2.2
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Bitca
101
+ test_files: []