opensecret 0.0.4 → 0.0.5
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.
- checksums.yaml +4 -4
- data/lib/config.openkey.ini +14 -0
- data/lib/opensecret/plugins.io/cipher/crypto.rb +152 -123
- data/lib/opensecret/version.rb +1 -1
- data/lib/opensecret.rb +63 -11
- metadata +2 -2
- data/lib/opensecret-domain.ini +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bc4bfc60cbda290f4cac72f199f16c7edeee9f7
|
4
|
+
data.tar.gz: 5b901aaa8a3d2db04a48bb1244bf9e305e7ab2a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e246d8520e068d0dace4ec48221d0cc2a2fbd761e8c06924759912e24e1e9afbdb433e56b1a132983966c178b3ae79fa30ded31fa9e57d287c4d9cf50d844d3
|
7
|
+
data.tar.gz: 8b0cee1a18cb39cfce967b73dd091630d6f8ac923b7d60978a1d61970d157a41f67be672653c19798e25dd3a306002a385ba19a47940e193552665373cffcf5b
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
[joebloggs@openkey.com]
|
3
|
+
type=user
|
4
|
+
id=joe
|
5
|
+
keydir=/media/usb-key/secrets
|
6
|
+
fingerprint=23423x123123
|
7
|
+
public.key.signature=13242345dfg
|
8
|
+
|
9
|
+
[blues.band.bloggs]
|
10
|
+
type=domain
|
11
|
+
members = { pete => "peterpan@simple.com", fx => "admin@fortknox.com" }
|
12
|
+
fingerprints = { pete => "x1234ljsdf", fx => "asdfasd1234" }
|
13
|
+
store.url=https://www.github.com/joes.hub.account
|
14
|
+
|
@@ -1,174 +1,203 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
#
|
6
|
+
# Create dynamic secrets of various flavours including
|
7
|
+
#
|
8
|
+
# - ssh public/private key secrets
|
9
|
+
# - secret keys for internal database services
|
10
|
+
# - hashed SHA256 keys for Jenkins user auth
|
11
|
+
#
|
12
|
+
class Crypto
|
13
|
+
|
14
|
+
|
15
|
+
# Register two fundamental openkey crypt pointers
|
16
|
+
#
|
17
|
+
# - an openkey domain like » **lecturers@harvard**
|
18
|
+
# - the url to a backend store like Git, S3 or an SSH accessible drive.
|
19
|
+
#
|
20
|
+
# The domain will be extended to cover verified internet domains.
|
21
|
+
# They will also latch onto LDAP domains so when admins add, revoke
|
22
|
+
# or remove users, their openkey access is adjusted accordingly.
|
23
|
+
#
|
24
|
+
# @param domain [String] the DOMAIN eg lecturers@harvard for your family or work group.
|
25
|
+
# @param store_url [String] the STORE_URL for connecting to the backend storage service
|
26
|
+
#
|
27
|
+
def self.register_domain domain, store_url
|
28
|
+
|
29
|
+
# -> read config file map
|
30
|
+
# -> create new domain in map
|
31
|
+
# -> add type and store url to map
|
32
|
+
# -> backup configuration
|
33
|
+
# -> overwrite the ini config file
|
34
|
+
puts "hello i am registering this super domain #{domain} at #{store_url}"
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# --
|
40
|
+
# -- Get a viable machine password taking into account the human
|
41
|
+
# -- password length and the specified mix_ratio.
|
42
|
+
# --
|
43
|
+
# -- machine password length = human password length * mix_ratio - 1
|
44
|
+
# --
|
45
|
+
def self.get_amalgam_password human_password, machine_password, mix_ratio
|
46
|
+
|
47
|
+
size_error_msg = "Human pass length times mix_ratio must equal machine pass length."
|
48
|
+
lengths_are_perfect = human_password.length * mix_ratio == machine_password.length
|
49
|
+
raise ArgumentError.new size_error_msg unless lengths_are_perfect
|
50
|
+
|
51
|
+
machine_passwd_chunk = 0
|
52
|
+
amalgam_passwd_index = 0
|
53
|
+
amalgamated_password = ""
|
54
|
+
|
55
|
+
human_password.each_char do |passwd_char|
|
56
|
+
|
57
|
+
amalgamated_password[amalgam_passwd_index] = passwd_char
|
36
58
|
amalgam_passwd_index += 1
|
59
|
+
|
60
|
+
for i in 0..(mix_ratio-1) do
|
61
|
+
machine_pass_index = machine_passwd_chunk * mix_ratio + i
|
62
|
+
amalgamated_password[amalgam_passwd_index] = machine_password[machine_pass_index]
|
63
|
+
amalgam_passwd_index += 1
|
64
|
+
end
|
65
|
+
|
66
|
+
machine_passwd_chunk += 1
|
67
|
+
|
37
68
|
end
|
38
69
|
|
39
|
-
|
70
|
+
return amalgamated_password
|
40
71
|
|
41
72
|
end
|
42
73
|
|
43
|
-
return amalgamated_password
|
44
74
|
|
45
|
-
|
75
|
+
# --
|
76
|
+
# -- Get a viable machine password taking into account the human
|
77
|
+
# -- password length and the specified mix_ratio.
|
78
|
+
# --
|
79
|
+
# -- machine password length = human password length * mix_ratio - 1
|
80
|
+
# --
|
81
|
+
def self.get_machine_password human_password_length, mix_ratio
|
46
82
|
|
47
|
-
|
48
|
-
|
49
|
-
# -- password length and the specified mix_ratio.
|
50
|
-
# --
|
51
|
-
# -- machine password length = human password length * mix_ratio - 1
|
52
|
-
# --
|
53
|
-
def self.get_machine_password human_password_length, mix_ratio
|
83
|
+
machine_raw_secret = engineer_password( human_password_length * ( mix_ratio + 1) )
|
84
|
+
return machine_raw_secret[ 0..( human_password_length * mix_ratio - 1 ) ]
|
54
85
|
|
55
|
-
|
56
|
-
return machine_raw_secret[ 0..( human_password_length * mix_ratio - 1 ) ]
|
86
|
+
end
|
57
87
|
|
58
|
-
end
|
59
88
|
|
89
|
+
# --
|
90
|
+
# -- Collect a password from the user with a minimum length
|
91
|
+
# -- specified in the parameter.
|
92
|
+
# --
|
93
|
+
# -- An exception is raised if the minimum length is not at
|
94
|
+
# -- least 8 characters.
|
95
|
+
# --
|
96
|
+
def self.collect_secret minimum_size, prompt_1, prompt_2
|
60
97
|
|
61
|
-
|
62
|
-
# -- Collect a password from the user with a minimum length
|
63
|
-
# -- specified in the parameter.
|
64
|
-
# --
|
65
|
-
# -- An exception is raised if the minimum length is not at
|
66
|
-
# -- least 8 characters.
|
67
|
-
# --
|
68
|
-
def self.collect_secret minimum_size, prompt_1, prompt_2
|
98
|
+
assert_min_size minimum_size
|
69
99
|
|
70
|
-
|
100
|
+
sleep(1)
|
101
|
+
puts "\n#{prompt_1} : "
|
102
|
+
first_secret = STDIN.noecho(&:gets).chomp
|
71
103
|
|
72
|
-
|
73
|
-
puts "\n#{prompt_1} : "
|
74
|
-
first_secret = STDIN.noecho(&:gets).chomp
|
104
|
+
assert_input_text_size first_secret.length, minimum_size
|
75
105
|
|
76
|
-
|
106
|
+
sleep(1)
|
107
|
+
puts "\n#{prompt_2} : "
|
108
|
+
check_secret = STDIN.noecho(&:gets).chomp
|
77
109
|
|
78
|
-
|
79
|
-
|
80
|
-
|
110
|
+
assert_same_size_text first_secret, check_secret
|
111
|
+
|
112
|
+
return first_secret
|
81
113
|
|
82
|
-
|
83
|
-
|
84
|
-
return first_secret
|
114
|
+
end
|
85
115
|
|
86
|
-
end
|
87
116
|
|
117
|
+
# --
|
118
|
+
# -- Engineer a raw password that is similar (approximate) in
|
119
|
+
# -- length to the integer parameter.
|
120
|
+
# --
|
121
|
+
def self.engineer_password approx_length
|
88
122
|
|
89
|
-
|
90
|
-
|
91
|
-
# -- length to the integer parameter.
|
92
|
-
# --
|
93
|
-
def self.engineer_password approx_length
|
123
|
+
non_alphanum = SecureRandom.urlsafe_base64(approx_length);
|
124
|
+
return non_alphanum.delete("-_")
|
94
125
|
|
95
|
-
|
96
|
-
return non_alphanum.delete("-_")
|
126
|
+
end
|
97
127
|
|
98
|
-
end
|
99
128
|
|
129
|
+
# --
|
130
|
+
# -- Raise an exception if asked to collect text that is less
|
131
|
+
# -- than 3 characters in length.
|
132
|
+
# --
|
133
|
+
def self.assert_min_size minimum_size
|
100
134
|
|
101
|
-
|
102
|
-
|
103
|
-
# -- than 3 characters in length.
|
104
|
-
# --
|
105
|
-
def self.assert_min_size minimum_size
|
135
|
+
min_length_msg = "\n\nCrypts with 2 (or less) characters open up exploitable holes.\n\n"
|
136
|
+
raise ArgumentError.new min_length_msg if minimum_size < 3
|
106
137
|
|
107
|
-
|
108
|
-
raise ArgumentError.new min_length_msg if minimum_size < 3
|
138
|
+
end
|
109
139
|
|
110
|
-
end
|
111
140
|
|
141
|
+
# --
|
142
|
+
# -- Output an error message and then exit if the entered input
|
143
|
+
# -- text size does not meet the minimum requirements.
|
144
|
+
# --
|
145
|
+
def self.assert_input_text_size input_size, minimum_size
|
112
146
|
|
113
|
-
|
114
|
-
# -- Output an error message and then exit if the entered input
|
115
|
-
# -- text size does not meet the minimum requirements.
|
116
|
-
# --
|
117
|
-
def self.assert_input_text_size input_size, minimum_size
|
147
|
+
if( input_size < minimum_size )
|
118
148
|
|
119
|
-
|
149
|
+
puts
|
150
|
+
puts "Input is too short. Please enter at least #{minimum_size} characters."
|
151
|
+
puts
|
120
152
|
|
121
|
-
|
122
|
-
puts "Input is too short. Please enter at least #{minimum_size} characters."
|
123
|
-
puts
|
153
|
+
exit
|
124
154
|
|
125
|
-
|
155
|
+
end
|
126
156
|
|
127
157
|
end
|
128
158
|
|
129
|
-
end
|
130
159
|
|
160
|
+
# --
|
161
|
+
# -- Assert that the text entered the second time is exactly (case sensitive)
|
162
|
+
# -- the same as the text entered the first time.
|
163
|
+
# --
|
164
|
+
def self.assert_same_size_text first_text, second_text
|
165
|
+
|
166
|
+
unless( first_text.eql? second_text )
|
131
167
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
# --
|
136
|
-
def self.assert_same_size_text first_text, second_text
|
137
|
-
|
138
|
-
unless( first_text.eql? second_text )
|
168
|
+
puts
|
169
|
+
puts "Those two bits of text are not the same (in my book)!"
|
170
|
+
puts
|
139
171
|
|
140
|
-
|
141
|
-
puts "Those two bits of text are not the same (in my book)!"
|
142
|
-
puts
|
172
|
+
exit
|
143
173
|
|
144
|
-
|
174
|
+
end
|
145
175
|
|
146
176
|
end
|
147
177
|
|
148
|
-
end
|
149
178
|
|
179
|
+
# --
|
180
|
+
# -- Print out the machine password that is to be kept as an environment variable
|
181
|
+
# -- on any workstation used for material decryption.
|
182
|
+
# --
|
183
|
+
# -- Remember that neither the human nor machine passwords are required for the
|
184
|
+
# -- encryption phase. That is the beauty of assymetric cryptography - you don't
|
185
|
+
# -- need a private key to encrypt - just the end user's public key.
|
186
|
+
# --
|
187
|
+
def self.print_secret_env_var env_var_name, env_var_value
|
150
188
|
|
151
|
-
|
152
|
-
# -- Print out the machine password that is to be kept as an environment variable
|
153
|
-
# -- on any workstation used for material decryption.
|
154
|
-
# --
|
155
|
-
# -- Remember that neither the human nor machine passwords are required for the
|
156
|
-
# -- encryption phase. That is the beauty of assymetric cryptography - you don't
|
157
|
-
# -- need a private key to encrypt - just the end user's public key.
|
158
|
-
# --
|
159
|
-
def self.print_secret_env_var env_var_name, env_var_value
|
189
|
+
machine_to_env_txt = "sudo echo \"#{env_var_name}=#{env_var_value}\" >> /etc/environment"
|
160
190
|
|
161
|
-
|
191
|
+
puts
|
192
|
+
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
193
|
+
puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
194
|
+
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
195
|
+
puts machine_to_env_txt
|
196
|
+
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
197
|
+
puts
|
162
198
|
|
163
|
-
|
164
|
-
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
165
|
-
puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
166
|
-
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
167
|
-
puts machine_to_env_txt
|
168
|
-
puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
169
|
-
puts
|
199
|
+
end
|
170
200
|
|
171
201
|
end
|
172
202
|
|
173
|
-
|
174
203
|
end
|
data/lib/opensecret/version.rb
CHANGED
data/lib/opensecret.rb
CHANGED
@@ -1,13 +1,42 @@
|
|
1
1
|
require "opensecret/version"
|
2
2
|
require "thor"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# # How domains are joined?
|
5
|
+
#
|
6
|
+
# First the user **wishing to join* must be able to access the domain shared
|
7
|
+
# **backend storage** system. The planned list of supported storage systems (each of
|
8
|
+
# which is on-lined with a plugin (in plugins.io) is
|
9
|
+
#
|
10
|
+
# - Git (including GitHub, GitLab, BitBucket, OpenGit and private Git installations).
|
11
|
+
# - S3 Buckets from the Amazon Web Services (AWS) cloud.
|
12
|
+
# - SSH, SCP, SFTP connected file-systems
|
13
|
+
# - network storage including Samba, NFS, VMWare vSAN
|
14
|
+
# - GoogleDrive (only Windows has suitable synchronized support).
|
15
|
+
# - DropBox
|
16
|
+
#
|
17
|
+
# Access management is configured EXTERNAL to openkey. OpenKey simply piggybacks
|
18
|
+
# the network transport if authorization is granted.
|
9
19
|
#
|
10
|
-
#
|
20
|
+
# ## Use Case - Joining a Domain
|
21
|
+
#
|
22
|
+
# - ok will loop encrypting your public key's fingerprint with the public keys of present members
|
23
|
+
# - when they interact ok will ask if they trust the new id/email and key
|
24
|
+
# - if they say yes the fingerprint is imported and held with id/name
|
25
|
+
# - ongoing domainwide checks flag up public key / fingerprint mismatches
|
26
|
+
# - if keys are removed or updated similar questions are asked.
|
27
|
+
#
|
28
|
+
# # Begging for and Revealing Secrets
|
29
|
+
#
|
30
|
+
# - Why beg for a secret - why not just tell someone it?
|
31
|
+
# - It is much more secure to beg for a secret than just have someone reveal it.
|
32
|
+
# - When you beg for a secret - you are sending an encryption key to a single person
|
33
|
+
# - who must possess the private key and they send back the secret encrypted with both
|
34
|
+
# - your specific public key and the encryption key that originated from you.
|
35
|
+
# -
|
36
|
+
# - Any hijacker will need access to a great many things and be very precise with their
|
37
|
+
# - timing in order to serrupticiously subvert the system.
|
38
|
+
#
|
39
|
+
# ### This command line processor will
|
11
40
|
#
|
12
41
|
# - read the posted commands, options and switches
|
13
42
|
# - maps the incoming string data to objects
|
@@ -18,15 +47,38 @@ end
|
|
18
47
|
#
|
19
48
|
# @note the Thor ruby gem is used for the heavy lifting
|
20
49
|
#
|
50
|
+
# @example openkey initdomain create friends.joebloggs --secure
|
51
|
+
# @example openkey user create id=joe email=joebloggs@openkey.com
|
52
|
+
# @example openkey user create id=joe email=joebloggs@openkey.com
|
53
|
+
#
|
54
|
+
#
|
21
55
|
class CommandProcessor < Thor
|
22
56
|
|
23
|
-
|
57
|
+
desc "init DOMAIN", "DOMAIN eg lecturers@harvard names your friends, family or work group."
|
58
|
+
desc "init STORE_URL", "STORE_URL is backend Git/S3/SSH crypt store. Use https://www.eco-platform.co.uk/crypt.store.git"
|
59
|
+
|
60
|
+
# Initialize (configure) two fundamental crypt pointers
|
61
|
+
#
|
62
|
+
# - an openkey domain like » **lecturers@harvard**
|
63
|
+
# - the url to a backend store like Git, S3 or an SSH accessible drive.
|
64
|
+
#
|
65
|
+
# The domain will be extended to cover verified internet domains.
|
66
|
+
# They will also latch onto LDAP domains so when admins add, revoke
|
67
|
+
# or remove users, their openkey access is adjusted accordingly.
|
68
|
+
#
|
69
|
+
# @example openkey user create id=joe email=joebloggs@openkey.com
|
70
|
+
#
|
71
|
+
# @param domain [String] the DOMAIN eg lecturers@harvard for your family or work group.
|
72
|
+
# @param store_url [String] the STORE_URL for connecting to the backend storage service
|
73
|
+
#
|
74
|
+
def init domain, store_url
|
24
75
|
|
25
|
-
|
26
|
-
def init( domain )
|
76
|
+
OpenSecret::Crypto.register_domain domain, store_url
|
27
77
|
|
28
|
-
puts "
|
29
|
-
|
78
|
+
puts ""
|
79
|
+
puts "New domain configured => [ #{domain} ]"
|
80
|
+
puts "Crypt store configured => [ #{store_url} ]"
|
81
|
+
puts ""
|
30
82
|
|
31
83
|
end
|
32
84
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opensecret
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Apollo Akora
|
@@ -99,7 +99,7 @@ files:
|
|
99
99
|
- README.md
|
100
100
|
- Rakefile
|
101
101
|
- bin/opensecret
|
102
|
-
- lib/
|
102
|
+
- lib/config.openkey.ini
|
103
103
|
- lib/opensecret.rb
|
104
104
|
- lib/opensecret/additions/array.rb
|
105
105
|
- lib/opensecret/additions/dir.rb
|
data/lib/opensecret-domain.ini
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
opensecret configure mode="secure"
|
7
|
-
opensecret configure mode="secure"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
[@[os|domain.id]]
|
13
|
-
|
14
|
-
secrecy = play # Options are play | secure | enterprise see website for details.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
[people]
|
19
|
-
|
20
|
-
jack = jackhiggins@blueyonder.com
|
21
|
-
gaz = gareth.southgate@gmail.com
|
22
|
-
jiji = johnjames23@yahoo.co.uk
|
23
|
-
|