thales-pse 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9822d9ede725eb7e93e61f5da6edd57880e9085263fac58f4e0d28ac72949747
4
+ data.tar.gz: c3c6041f5dbde1e17a4709092be0a425f752f11535fb2db9074cb39d2a19abbb
5
+ SHA512:
6
+ metadata.gz: 8bfc6a8cd47b76425c40c9d00959997583d07c5a62394a7e6f928ff367d89905c5dbcc189c0aebbc780a1e33753501c980b2bd74dc09f5403732e327e78d3f3b
7
+ data.tar.gz: 51661eade08e5edfd65a7d61a2e3d4e32978e5c07aebb0552067ef92623e091b44f9e8e1d7b39eda3ea916f9d45315ef99819ae2ff8b7fca49e55d2aa644b0e7
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in thales-pse.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ #gem 'toolrack', path: '/mnt/Vault/08.Dev/01.Workspaces/WIP/toolrack'
13
+
data/Gemfile.lock ADDED
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ thales-pse (0.1.0)
5
+ tlogger
6
+ toolrack
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ base58 (0.2.3)
12
+ devops_helper (0.5.0)
13
+ git_cli
14
+ gvcs
15
+ tlogger
16
+ toolrack
17
+ tty-prompt (= 0.22.0)
18
+ diff-lcs (1.4.4)
19
+ git_cli (0.8.0)
20
+ gvcs (>= 0.1.0)
21
+ ptools (~> 1.4.0)
22
+ tlogger (>= 0.21)
23
+ toolrack (>= 0.4.0)
24
+ gvcs (0.1.0)
25
+ pastel (0.8.0)
26
+ tty-color (~> 0.5)
27
+ ptools (1.4.2)
28
+ rake (13.0.6)
29
+ rspec (3.10.0)
30
+ rspec-core (~> 3.10.0)
31
+ rspec-expectations (~> 3.10.0)
32
+ rspec-mocks (~> 3.10.0)
33
+ rspec-core (3.10.1)
34
+ rspec-support (~> 3.10.0)
35
+ rspec-expectations (3.10.1)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.10.0)
38
+ rspec-mocks (3.10.2)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.10.0)
41
+ rspec-support (3.10.2)
42
+ tlogger (0.26.1)
43
+ toolrack (0.15.0)
44
+ base58
45
+ tlogger
46
+ tty-color (0.6.0)
47
+ tty-cursor (0.7.1)
48
+ tty-prompt (0.22.0)
49
+ pastel (~> 0.8)
50
+ tty-reader (~> 0.8)
51
+ tty-reader (0.9.0)
52
+ tty-cursor (~> 0.7)
53
+ tty-screen (~> 0.8)
54
+ wisper (~> 2.0)
55
+ tty-screen (0.8.1)
56
+ wisper (2.0.1)
57
+
58
+ PLATFORMS
59
+ java
60
+ universal-java-1.8
61
+ x86_64-linux
62
+
63
+ DEPENDENCIES
64
+ devops_helper
65
+ rake (~> 13.0)
66
+ rspec (~> 3.0)
67
+ thales-pse!
68
+
69
+ BUNDLED WITH
70
+ 2.2.28
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Thales::Pse
2
+
3
+ Collection of utilities to integrates with the Thales (Previously SafeNet) ProtectServer External (PSE) HSM.
4
+
5
+ It is tested to ease the usage for local development with the simulator. Not for production use.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'thales-pse'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install thales-pse
22
+
23
+ ## Usage
24
+
25
+ Check the usage inside the spec/thales/hsm\_spec.rb
26
+
27
+ Currently it is just API to assist in setting up the HSM for usage.
28
+
29
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ require 'devops_helper'
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "thales/pse"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,69 @@
1
+
2
+ require 'pty'
3
+ require 'expect'
4
+ require 'timeout'
5
+
6
+ module Thales
7
+ module Pse
8
+ module Cli
9
+ include TR::CondUtils
10
+ include TR::CliUtils
11
+
12
+ class ExecutableNotFoundError < StandardError; end
13
+
14
+ def cli_exec(exec, &block)
15
+
16
+ exePath = which(exec)
17
+ raise ExecutableNotFoundError, "#{exec} cannot be found" if is_empty?(exePath)
18
+ raise Error, "Block is required" if not block
19
+
20
+ params = block.call(:params) || []
21
+ expect_list = block.call(:expect_list)
22
+
23
+ output = block.call(:output) || TR::NullOut.new
24
+
25
+ cmd = "#{exePath} #{params.join(" ")}"
26
+
27
+ logger.tdebug :cmd, "cli_exec command : #{cmd}"
28
+
29
+ PTY.spawn(exePath, *params) do |read, write, pid|
30
+
31
+ begin
32
+
33
+ if not is_empty?(expect_list)
34
+ expect_list.each do |ex|
35
+ to = ex[:timeout] || 1
36
+ cont = read.expect(/#{ex[:matcher]}/, to)
37
+ output.puts cont
38
+ write.puts block.call(ex[:block_key], cont)
39
+ end
40
+ end
41
+
42
+ Timeout.timeout(1) do
43
+ read.each do |l|
44
+ output.puts l if not_empty?(l)
45
+ end
46
+ end
47
+
48
+ rescue Timeout::Error => e
49
+ read.close
50
+ write.close
51
+ Process.kill('TERM',pid)
52
+ output.puts "Process #{cmd} ('#{pid}') killed due to timeout"
53
+ rescue Errno::EIO
54
+ output.puts "[Done] #{cmd}"
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ def logger
61
+ if @logger.nil?
62
+ @logger = Tlogger.new
63
+ end
64
+ @logger
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,313 @@
1
+
2
+ require 'pty'
3
+ require 'expect'
4
+ require 'toolrack'
5
+ require 'timeout'
6
+
7
+ require_relative 'cli'
8
+
9
+ module Thales
10
+ module Pse
11
+ module Config
12
+ include TR::CondUtils
13
+ include TR::CliUtils
14
+ include Cli
15
+
16
+ def init(&block)
17
+
18
+ expect = [
19
+ { key: "enter new Admin SO pin:", block_key: :admin_so_pin, timeout: 1 },
20
+ { key: "confirm new Admin SO pin:", block_key: :admin_so_pin_confirm, timeout: 1 },
21
+ { key: "enter new Administrator\'s pin:", block_key: :admin_pin, timeout: 1 },
22
+ { key: "confirm new Administrator\'s pin:", block_key: :admin_pin_confirm, timeout: 1 }
23
+ ]
24
+
25
+ begin
26
+
27
+ cli_exec("ctconf") do |ops|
28
+ case ops
29
+ when :expect_list
30
+ expect
31
+ else
32
+ block.call(ops)
33
+ end
34
+ end
35
+
36
+ rescue ExecutableNotFoundError
37
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
38
+ end
39
+
40
+ end
41
+
42
+ def init_token(&block)
43
+
44
+ raise Error, "Block is required" if not block
45
+
46
+ expect = [
47
+ { key: "new token label:", block_key: :token_label, timeout: 1 },
48
+ { key: "enter Security Officer\'s pin:", block_key: :token_so_pin, timeout: 1 },
49
+ { key: "confirm Security Officer\'s pin:", block_key: :token_so_pin_confirm, timeout: 1 }
50
+ ]
51
+
52
+ slot = block.call(:slot) || 0
53
+
54
+ begin
55
+
56
+ cli_exec("ctconf") do |ops|
57
+ case ops
58
+ when :params
59
+ ["-n#{slot}"]
60
+ when :expect_list
61
+ expect
62
+ else
63
+ block.call(ops)
64
+ end
65
+ end
66
+
67
+ rescue ExecutableNotFoundError
68
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
69
+ end
70
+
71
+ end
72
+
73
+ def init_user_pin(&block)
74
+
75
+ raise Error, "Block is required" if not block
76
+
77
+ expect = [
78
+ # this key is handled locally not passed to external
79
+ { key: "Security Officer PIN.+:|current user PIN.+:", block_key: :auth_pin, timeout: 3 },
80
+ { key: "enter the new user PIN.+:", block_key: :token_user_pin, timeout: 1 },
81
+ { key: "confirm the new user PIN.+:", block_key: :token_user_pin_confirm, timeout: 1 }
82
+ ]
83
+
84
+ slot = block.call(:slot) || 0
85
+
86
+ begin
87
+
88
+ cli_exec("ctkmu") do |ops, val|
89
+ case ops
90
+ when :params
91
+ ["p","-s#{slot}"]
92
+ when :expect_list
93
+ expect
94
+ when :auth_pin
95
+ if not_empty?(val)
96
+ if val.join =~ /Security Officer/
97
+ block.call(:token_so_pin)
98
+ else
99
+ block.call(:token_user_pin)
100
+ end
101
+ end
102
+ else
103
+ block.call(ops)
104
+ end
105
+ end
106
+
107
+ rescue ExecutableNotFoundError
108
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
109
+ end
110
+
111
+ end
112
+
113
+
114
+ def genkey(type, &block)
115
+
116
+ raise Error, "Block is required" if not block
117
+
118
+ expect = [
119
+ { key: "Enter user PIN.+:", block_key: :slot_user_pin, timeout: 1 }
120
+ ]
121
+
122
+ case type
123
+ when :rsa
124
+ else
125
+ raise Error, "Unsupported key type #{type}"
126
+ end
127
+
128
+ slot = block.call(:slot) || 0
129
+
130
+ name = block.call(:name)
131
+ raise Error, "Name is required " if is_empty?(name)
132
+ name.gsub!(" ","_")
133
+
134
+ attr = block.call(:attr)
135
+ raise Error, "Attributes (attr) is required " if is_empty?(attr)
136
+ attr = [attr] if not attr.is_a?(Array)
137
+ atRes = []
138
+ attr.each do |at|
139
+ case at
140
+ when :private
141
+ atRes << "P"
142
+ when :modifiable
143
+ atRes << "M"
144
+ when :sensitive
145
+ atRes << "T"
146
+ when :wrap
147
+ atRes << "W"
148
+ when :export
149
+ atRes << "w"
150
+ when :import
151
+ atRes << "I"
152
+ when :unwrap
153
+ atRes << "U"
154
+ when :extractable
155
+ atRes << "X"
156
+ when :exportable
157
+ atRes << "x"
158
+ when :derive
159
+ atRes << "R"
160
+ when :encrypt
161
+ atRes << "E"
162
+ when :decrypt
163
+ atRes << "D"
164
+ when :sign
165
+ atRes << "S"
166
+ when :verify
167
+ atRes << "V"
168
+ when :sign_local_cert
169
+ atRes << "L"
170
+ when :usage_count
171
+ atRes << "C"
172
+ end
173
+ end
174
+
175
+ keysize = block.call(:keysize) || 2048
176
+
177
+ begin
178
+
179
+ cli_exec("ctkmu") do |ops, val|
180
+ case ops
181
+ when :params
182
+ ["c","-t#{type}","-s#{slot}","-n#{name}","-a#{atRes.join}"]
183
+ when :expect_list
184
+ expect
185
+ else
186
+ block.call(ops)
187
+ end
188
+ end
189
+
190
+ rescue ExecutableNotFoundError
191
+ raise Error, "Executable 'ctkmu' not found from PATH. Please install the driver or add the executable to PATH"
192
+ end
193
+
194
+
195
+ end
196
+
197
+ def gencert(&block)
198
+
199
+ raise Error, "Block is required" if not block
200
+
201
+ expect = [
202
+ { key: "Enter user PIN.+:", block_key: :slot_user_pin, timeout: 1 },
203
+ ]
204
+
205
+ keylabel = block.call(:keylabel)
206
+ raise Error, "Keylabel should not be empty" if is_empty?(keylabel)
207
+ keylabel.gsub!(" ","_")
208
+
209
+ slot = block.call(:slot)
210
+ validFrom = block.call(:valid_from)
211
+ #if is_empty?(validFrom) or not validFrom.is_a?(Time)
212
+ # today = Time.now
213
+ # validFrom = Time.new(today.year, today.month, today.day)
214
+ #end
215
+ validity = block.call(:validity)
216
+ if not (validity =~ /h|d|m|y/)
217
+ raise Error, "Validity requires unit in hour (h), day (d), month (m) or year (y)"
218
+ end
219
+ validTo = block.call(:valid_to)
220
+ raise Error, "Valid_to requires a time object" if (not_empty?(validTo) and not validTo.is_a?(Time))
221
+
222
+ slot = block.call(:slot) || 0
223
+ certFile = block.call(:cert_file)
224
+
225
+ cn = block.call(:common_name)
226
+ raise Error, "Common name is mandatory" if is_empty?(cn)
227
+ expect << { key: "Common Name:", block_key: :cn, timeout: 1 }
228
+ org = block.call(:org)
229
+ expect << { key: "Organization:", block_key: :org, timeout: 1 }
230
+ ou = block.call(:ou)
231
+ expect << { key: "Organizational Unit:", block_key: :ou, timeout: 1 }
232
+ loc = block.call(:locality)
233
+ expect << { key: "Locality:", block_key: :loc, timeout: 1 }
234
+ st = block.call(:state)
235
+ expect << { key: "State:", block_key: :st, timeout: 1 }
236
+ ctry = block.call(:country)
237
+ expect << { key: "Country:", block_key: :ctry, timeout: 1 }
238
+ sn = block.call(:serial_no) || SecureRandom.uuid.gsub("-","")
239
+ expect << { key: "certificate\'s serial number.+:", block_key: :sn, timeout: 1 }
240
+
241
+ params = ["c","-l#{keylabel}", "-s#{slot}"]
242
+ if not_empty?(validFrom)
243
+ params << "-b#{validFrom.strftime("%Y%m%d%H%M%S")}"
244
+ end
245
+ if not_empty?(validity)
246
+ params << "-d#{validity}"
247
+ end
248
+ if not_empty?(validTo)
249
+ params << "-e#{validTo.strftime("%Y%m%d%H%M%S")}"
250
+ end
251
+
252
+ begin
253
+
254
+ cli_exec("ctcert") do |ops, val|
255
+ case ops
256
+ when :params
257
+ params
258
+ when :expect_list
259
+ expect
260
+ when :cn
261
+ cn
262
+ when :org
263
+ org
264
+ when :ou
265
+ ou
266
+ when :loc
267
+ loc
268
+ when :st
269
+ st
270
+ when :ctry
271
+ ctry
272
+ when :sn
273
+ sn
274
+ else
275
+ block.call(ops)
276
+ end
277
+ end
278
+
279
+ rescue ExecutableNotFoundError
280
+ raise Error, "Executable 'ctkmu' not found from PATH. Please install the driver or add the executable to PATH"
281
+ end
282
+
283
+ if not_empty?(certFile)
284
+ export_cert(keylabel, certFile, slot)
285
+ end
286
+
287
+ end # gencert
288
+
289
+ def export_cert(label, outFile, slot = 0, &block)
290
+
291
+ raise Error, "Key label cannot be empty" if is_empty?(label)
292
+ raise Error, "Output file cannot be empty" if is_empty?(outFile)
293
+
294
+ label.gsub!(" ","_")
295
+
296
+ begin
297
+
298
+ cli_exec("ctcert") do |ops|
299
+ case ops
300
+ when :params
301
+ ["x","-l#{label}","-s#{slot}","-f#{outFile}"]
302
+ end
303
+ end
304
+
305
+ rescue ExecutableNotFoundError
306
+ raise Error, "Executable 'ctcert' not found from PATH. Please install the driver or add the executable to PATH"
307
+ end
308
+
309
+ end # export_cert
310
+
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,75 @@
1
+
2
+ require_relative 'cli'
3
+ require_relative 'slot'
4
+
5
+ module Thales
6
+ module Pse
7
+
8
+ class HSM
9
+
10
+ def self.instance(eng = :cli)
11
+ case eng
12
+ when :cli
13
+ h = HSM.new
14
+ h.extend(Cli::HSM)
15
+ h
16
+ else
17
+ h = HSM.new
18
+ h.extend(Cli::HSM)
19
+ h
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ module Cli
26
+ module HSM
27
+ include TR::CondUtils
28
+ include TR::CliUtils
29
+ include Cli
30
+
31
+ def init_hsm(*args,&block)
32
+
33
+ expect = [
34
+ { matcher: "enter new Admin SO pin:", block_key: :admin_so_pin, timeout: 5 },
35
+ { matcher: "confirm new Admin SO pin:", block_key: :admin_so_pin_confirm, timeout: 5 },
36
+ { matcher: "enter new Administrator\'s pin:", block_key: :admin_pin, timeout: 5 },
37
+ { matcher: "confirm new Administrator\'s pin:", block_key: :admin_pin_confirm, timeout: 5 }
38
+ ]
39
+
40
+ begin
41
+
42
+ cli_exec("ctconf") do |ops|
43
+ case ops
44
+ when :expect_list
45
+ expect
46
+ else
47
+ block.call(ops)
48
+ end
49
+ end
50
+
51
+ rescue ExecutableNotFoundError
52
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
53
+ end
54
+
55
+
56
+ end
57
+
58
+ def default_user_slot
59
+ if @defUserSlot.nil?
60
+ @defUserSlot = Slot.new(0)
61
+ end
62
+ @defUserSlot
63
+ end
64
+
65
+ def default_admin_slot
66
+ if @defAdminSlot.nil?
67
+ @defAdminSlot = Slot.new(1)
68
+ end
69
+ @defAdminSlot
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require_relative 'token'
3
+
4
+ module Thales
5
+ module Pse
6
+ class Slot
7
+
8
+ attr_reader :id, :token
9
+ def initialize(id)
10
+ @id = id
11
+ end
12
+
13
+ def default_token
14
+ if @token.nil?
15
+ @token = Token.new(self)
16
+ end
17
+ @token
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,313 @@
1
+
2
+
3
+ require_relative 'cli'
4
+
5
+ module Thales
6
+ module Pse
7
+ module Cli
8
+ module Token
9
+ include TR::CondUtils
10
+ include TR::CliUtils
11
+ include Cli
12
+
13
+ def init_token(*args, &block)
14
+
15
+ init_token_so(&block)
16
+ init_token_user(&block)
17
+
18
+ end
19
+
20
+ def init_token_so(*args, &block)
21
+
22
+ raise TokenError, "Block is required" if not block
23
+ raise TokenError, "Slot is not available!" if is_empty?(@slot)
24
+
25
+ expect = [
26
+ { matcher: "new token label:", block_key: :token_label, timeout: 1 },
27
+ { matcher: "enter Security Officer\'s pin:", block_key: :token_so_pin, timeout: 1 },
28
+ { matcher: "confirm Security Officer\'s pin:", block_key: :token_so_pin_confirm, timeout: 1 }
29
+ ]
30
+
31
+ #slot = block.call(:slot) || 0
32
+ slot = @slot.id
33
+
34
+ begin
35
+
36
+ cli_exec("ctconf") do |ops|
37
+ case ops
38
+ when :params
39
+ ["-n#{slot}"]
40
+ when :expect_list
41
+ expect
42
+ else
43
+ block.call(ops)
44
+ end
45
+ end
46
+
47
+ rescue ExecutableNotFoundError
48
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
49
+ end
50
+
51
+ end
52
+
53
+ def init_token_user(*args, &block)
54
+
55
+ raise TokenError, "Block is required" if not block
56
+ raise TokenError, "Slot is not available!" if is_empty?(@slot)
57
+
58
+ expect = [
59
+ # this key is handled locally not passed to external
60
+ { matcher: "Security Officer PIN.+:|current user PIN.+:", block_key: :auth_pin, timeout: 3 },
61
+ { matcher: "enter the new user PIN.+:", block_key: :token_user_pin, timeout: 1 },
62
+ { matcher: "confirm the new user PIN.+:", block_key: :token_user_pin_confirm, timeout: 1 }
63
+ ]
64
+
65
+ #slot = block.call(:slot) || 0
66
+ slot = @slot.id
67
+
68
+ begin
69
+
70
+ cli_exec("ctkmu") do |ops, val|
71
+ case ops
72
+ when :params
73
+ ["p","-s#{slot}"]
74
+ when :expect_list
75
+ expect
76
+ when :auth_pin
77
+ if not_empty?(val)
78
+ if val.join =~ /Security Officer/
79
+ block.call(:token_so_pin)
80
+ else
81
+ block.call(:token_user_pin)
82
+ end
83
+ end
84
+ else
85
+ block.call(ops)
86
+ end
87
+ end
88
+
89
+ rescue ExecutableNotFoundError
90
+ raise Error, "Executable 'ctconf' not found from PATH. Please install the driver or add the executable to PATH"
91
+ end
92
+
93
+ end
94
+
95
+ def genkey(*args, &block)
96
+
97
+ raise TokenError, "Block is required" if not block
98
+ raise TokenError, "Slot is not available!" if is_empty?(@slot)
99
+
100
+ expect = [
101
+ { matcher: "Enter user PIN.+:", block_key: :token_user_pin, timeout: 1 }
102
+ ]
103
+
104
+ type = args.first
105
+ case type
106
+ when :rsa
107
+ else
108
+ raise Error, "Unsupported key type #{type}"
109
+ end
110
+
111
+ #slot = block.call(:slot) || 0
112
+ slot = @slot.id
113
+
114
+ keylabel = block.call(:keylabel)
115
+ raise Error, "Keylabel is required " if is_empty?(keylabel)
116
+ keylabel.gsub!(" ","_")
117
+
118
+ attr = block.call(:attr)
119
+ raise Error, "Attributes (attr) is required " if is_empty?(attr)
120
+ attr = [attr] if not attr.is_a?(Array)
121
+ atRes = []
122
+ attr.each do |at|
123
+ case at
124
+ when :private
125
+ atRes << "P"
126
+ when :modifiable
127
+ atRes << "M"
128
+ when :sensitive
129
+ atRes << "T"
130
+ when :wrap
131
+ atRes << "W"
132
+ when :export
133
+ atRes << "w"
134
+ when :import
135
+ atRes << "I"
136
+ when :unwrap
137
+ atRes << "U"
138
+ when :extractable
139
+ atRes << "X"
140
+ when :exportable
141
+ atRes << "x"
142
+ when :derive
143
+ atRes << "R"
144
+ when :encrypt
145
+ atRes << "E"
146
+ when :decrypt
147
+ atRes << "D"
148
+ when :sign
149
+ atRes << "S"
150
+ when :verify
151
+ atRes << "V"
152
+ when :sign_local_cert
153
+ atRes << "L"
154
+ when :usage_count
155
+ atRes << "C"
156
+ end
157
+ end
158
+
159
+ keysize = block.call(:keysize) || 2048
160
+
161
+ begin
162
+
163
+ cli_exec("ctkmu") do |ops, val|
164
+ case ops
165
+ when :params
166
+ ["c","-t#{type}","-s#{slot}","-n#{keylabel}","-a#{atRes.join}"]
167
+ when :expect_list
168
+ expect
169
+ else
170
+ block.call(ops)
171
+ end
172
+ end
173
+
174
+ rescue ExecutableNotFoundError
175
+ raise Error, "Executable 'ctkmu' not found from PATH. Please install the driver or add the executable to PATH"
176
+ end
177
+
178
+ end
179
+
180
+ def gencert(*args, &block)
181
+
182
+ raise TokenError, "Block is required" if not block
183
+ raise TokenError, "Slot is not available!" if is_empty?(@slot)
184
+
185
+ expect = [
186
+ { matcher: "Enter user PIN.+:", block_key: :token_user_pin, timeout: 1 },
187
+ ]
188
+
189
+ keylabel = block.call(:keylabel)
190
+ raise Error, "Keylabel should not be empty" if is_empty?(keylabel)
191
+ keylabel.gsub!(" ","_")
192
+
193
+ validFrom = block.call(:valid_from)
194
+ #if is_empty?(validFrom) or not validFrom.is_a?(Time)
195
+ # today = Time.now
196
+ # validFrom = Time.new(today.year, today.month, today.day)
197
+ #end
198
+ validity = block.call(:validity)
199
+ if not (validity =~ /h|d|m|y/)
200
+ raise Error, "Validity requires unit in hour (h), day (d), month (m) or year (y)"
201
+ end
202
+ validTo = block.call(:valid_to)
203
+ raise Error, "Valid_to requires a time object" if (not_empty?(validTo) and not validTo.is_a?(Time))
204
+
205
+ #slot = block.call(:slot) || 0
206
+ slot = @slot.id
207
+ certFile = block.call(:cert_file)
208
+
209
+ cn = block.call(:common_name)
210
+ raise Error, "Common name is mandatory" if is_empty?(cn)
211
+ expect << { matcher: "Common Name:", block_key: :cn, timeout: 1 }
212
+ org = block.call(:org)
213
+ expect << { matcher: "Organization:", block_key: :org, timeout: 1 }
214
+ ou = block.call(:ou)
215
+ expect << { matcher: "Organizational Unit:", block_key: :ou, timeout: 1 }
216
+ loc = block.call(:locality)
217
+ expect << { matcher: "Locality:", block_key: :loc, timeout: 1 }
218
+ st = block.call(:state)
219
+ expect << { matcher: "State:", block_key: :st, timeout: 1 }
220
+ ctry = block.call(:country)
221
+ expect << { matcher: "Country:", block_key: :ctry, timeout: 1 }
222
+ sn = block.call(:serial_no) || SecureRandom.uuid.gsub("-","")
223
+ expect << { matcher: "certificate\'s serial number.+:", block_key: :sn, timeout: 1 }
224
+
225
+ params = ["c","-l#{keylabel}", "-s#{slot}"]
226
+ if not_empty?(validFrom)
227
+ params << "-b#{validFrom.strftime("%Y%m%d%H%M%S")}"
228
+ end
229
+ if not_empty?(validity)
230
+ params << "-d#{validity}"
231
+ end
232
+ if not_empty?(validTo)
233
+ params << "-e#{validTo.strftime("%Y%m%d%H%M%S")}"
234
+ end
235
+
236
+ begin
237
+
238
+ cli_exec("ctcert") do |ops, val|
239
+ case ops
240
+ when :params
241
+ params
242
+ when :expect_list
243
+ expect
244
+ when :cn
245
+ cn
246
+ when :org
247
+ org
248
+ when :ou
249
+ ou
250
+ when :loc
251
+ loc
252
+ when :st
253
+ st
254
+ when :ctry
255
+ ctry
256
+ when :sn
257
+ sn
258
+ else
259
+ block.call(ops)
260
+ end
261
+ end
262
+
263
+ rescue ExecutableNotFoundError
264
+ raise Error, "Executable 'ctkmu' not found from PATH. Please install the driver or add the executable to PATH"
265
+ end
266
+
267
+ if not_empty?(certFile)
268
+ export_cert(keylabel, certFile)
269
+ end
270
+
271
+ end
272
+
273
+ def export_cert(label, outFile, &block)
274
+
275
+ raise TokenError, "Key label cannot be empty" if is_empty?(label)
276
+ raise TokenError, "Output file cannot be empty" if is_empty?(outFile)
277
+ raise TokenError, "Slot is not available!" if is_empty?(@slot)
278
+
279
+ slot = @slot.id
280
+ label.gsub!(" ","_")
281
+
282
+ begin
283
+
284
+ cli_exec("ctcert") do |ops|
285
+ case ops
286
+ when :params
287
+ ["x","-l#{label}","-s#{slot}","-f#{outFile}"]
288
+ end
289
+ end
290
+
291
+ rescue ExecutableNotFoundError
292
+ raise Error, "Executable 'ctcert' not found from PATH. Please install the driver or add the executable to PATH"
293
+ end
294
+
295
+
296
+ end
297
+
298
+ end
299
+ end # Cli
300
+
301
+ class Token
302
+ include Cli::Token
303
+
304
+ attr_accessor :slot
305
+ def initialize(slot)
306
+ @slot = slot
307
+ end
308
+
309
+ end
310
+
311
+ end
312
+
313
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thales
4
+ module Pse
5
+ VERSION = "0.1.1"
6
+ end
7
+ end
data/lib/thales/pse.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tlogger'
4
+ require 'toolrack'
5
+
6
+ require_relative "pse/version"
7
+ require_relative "pse/hsm"
8
+
9
+ module Thales
10
+ module Pse
11
+ class Error < StandardError; end
12
+
13
+ class HSMError < StandardError; end
14
+ class SlotError < StandardError; end
15
+ class TokenError < StandardError; end
16
+
17
+ # Your code goes here...
18
+
19
+
20
+ end
21
+ end
data/pty_test.rb ADDED
@@ -0,0 +1,23 @@
1
+
2
+ require 'pty'
3
+
4
+ prs, pws = PTY.open
5
+ r, w = IO.pipe
6
+
7
+ pid = spawn("/opt/safenet/protecttoolkit5/cpsdk/bin/linux-x86_64/ctconf 2>&1", in: r, out: pws)
8
+
9
+ r.close
10
+ pws.close
11
+
12
+ loop do
13
+ begin
14
+ line = prs.gets
15
+ rescue Errno::EIO => ex
16
+ p ex
17
+ Process.kill('TERM', pid)
18
+ break
19
+ end
20
+ end
21
+
22
+ puts "done"
23
+
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/thales/pse/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "thales-pse"
7
+ spec.version = Thales::Pse::VERSION
8
+ spec.authors = ["Ian"]
9
+ spec.email = ["cameronian0@protonmail.com"]
10
+
11
+ spec.summary = ""
12
+ spec.description = ""
13
+ spec.homepage = ""
14
+ spec.required_ruby_version = ">= 2.4.0"
15
+
16
+ #spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ #spec.metadata["homepage_uri"] = spec.homepage
19
+ #spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
20
+ #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_dependency 'tlogger'
34
+ spec.add_dependency 'toolrack'
35
+
36
+ spec.add_development_dependency "devops_helper"
37
+
38
+ # Uncomment to register a new dependency of your gem
39
+ # spec.add_dependency "example-gem", "~> 1.0"
40
+
41
+ # For more information and examples about making a new gem, checkout our
42
+ # guide at: https://bundler.io/guides/creating_gem.html
43
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thales-pse
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Ian
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-10-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tlogger
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: toolrack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: devops_helper
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: ''
56
+ email:
57
+ - cameronian0@protonmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".rspec"
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - README.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/setup
69
+ - lib/thales/pse.rb
70
+ - lib/thales/pse/cli.rb
71
+ - lib/thales/pse/config.rb
72
+ - lib/thales/pse/hsm.rb
73
+ - lib/thales/pse/slot.rb
74
+ - lib/thales/pse/token.rb
75
+ - lib/thales/pse/version.rb
76
+ - pty_test.rb
77
+ - thales-pse.gemspec
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: 2.4.0
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubygems_version: 3.2.22
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: ''
100
+ test_files: []