Birst_Command 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +48 -28
- data/bin/birstcl +32 -9
- data/lib/birst_command.rb +3 -1
- data/lib/birst_command/config.rb +4 -1
- data/lib/birst_command/core_additions.rb +8 -0
- data/lib/birst_command/password.rb +66 -0
- data/lib/birst_command/session.rb +1 -1
- data/lib/birst_command/version.rb +1 -1
- data/test/standard/test_password.rb +54 -0
- metadata +6 -7
- data/bin/obfuscate_pwd.rb +0 -9
- data/lib/birst_command/obfuscate.rb +0 -35
- data/test/standard/test_deobfuscate.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fcfeb6fbba597581204ab786c08a523038a34dd
|
4
|
+
data.tar.gz: 3aa45b83a061a5375c33d1a25caa0f7f9a242d2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06dc2ba21870c94529450d603469d216b77cbfd307d2b8ec2784404320273d367e40715dcd22d9a1a0597b9e6dae8ec8aab05c6e875745f84dfad97161350d38
|
7
|
+
data.tar.gz: 58252f327c73d797487fe37cb8e9f901400454c46495df153751ee12efbfb82f9a65c6c6baecc918ff2cda63d51b5ab9ad13d4efc63cb131111fb096c733d7e4
|
data/README.md
CHANGED
@@ -2,13 +2,17 @@ Birst_Command
|
|
2
2
|
====================
|
3
3
|
|
4
4
|
Birst Command is a Ruby gem that allows you to build Ruby scripts that
|
5
|
-
interface with the Birst Web API.
|
5
|
+
interface with the Birst Web API. It also comes with a simple command line
|
6
|
+
tool that can be used to execute simple API requests from the command line.
|
6
7
|
|
7
8
|
Note: this is not an officially-sanctioned Birst project. I'm just a
|
8
9
|
Birst user that needed to set up a very basic Ruby interface.
|
9
10
|
|
10
11
|
# Installation & Setup
|
11
12
|
|
13
|
+
**SPECIAL NOTE:** Password management has changed since version 0.3.0.
|
14
|
+
It is now more secure but requires some new configuration.
|
15
|
+
|
12
16
|
Prerequisites: Ruby > 2.0 and rubygems.
|
13
17
|
|
14
18
|
Install the gem using `gem install Birst_Command` or using rvm or
|
@@ -22,23 +26,38 @@ config file should look like,
|
|
22
26
|
"wsdl": "https://app2102.bws.birst.com/CommandWebService.asmx?WSDL",
|
23
27
|
"endpoint": "https://app2102.bws.birst.com/CommandWebService.asmx",
|
24
28
|
"username": "name@myplace.com",
|
25
|
-
"password": "
|
29
|
+
"password": "encrypted pwd"
|
26
30
|
}
|
27
31
|
|
28
|
-
Most users should only need to modify
|
29
|
-
password. (**Note**: do not use `login.bws.birst.com`
|
30
|
-
not use an updated WSDL; a specific app server must be
|
31
|
-
Since I have a strong aversion to storing passwords in
|
32
|
-
password in the config file needs to
|
33
|
-
Command comes with a password
|
32
|
+
Save it to `$HOME/.birstcl`. Most users should only need to modify
|
33
|
+
the username and password. (**Note**: do not use `login.bws.birst.com`
|
34
|
+
since it does not use an updated WSDL; a specific app server must be
|
35
|
+
specified). Since I have a strong aversion to storing passwords in
|
36
|
+
plaintext, the password in the config file needs to use and encrypted
|
37
|
+
password. Birst Command comes with a password encryptor that can be
|
38
|
+
executed via
|
34
39
|
|
35
|
-
|
36
|
-
|
40
|
+
````bash
|
41
|
+
$ birstcl -e mypassword
|
42
|
+
````
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
which should give an output similar to
|
45
|
+
````
|
46
|
+
Set these keys as environment variables
|
47
|
+
- Do not lose them or you will have to regenerate your password.
|
48
|
+
- Keep them secure, your password is compromised if these keys are compromised.
|
49
|
+
- Remove them as environment variables to generate new ones
|
50
|
+
BIRST_COMMAND_IV="3Nn26chRPkclusqTHePpig=="
|
51
|
+
BIRST_COMMAND_KEY="MWHa7gksYQaZTTq4snjyOnBDWUnKaVJq1VF4cv82MgA="
|
52
|
+
BIRST_COMMAND_SALT="KI//0xfSrX4mdSpiSp69BQ=="
|
53
|
+
...
|
54
|
+
Use this encrypted password in your .birstcl file: "JlCX9/RvHnGuWZWUcjTelg=="
|
55
|
+
````
|
56
|
+
|
57
|
+
Copy and paste the encrypted password into the config file. You will
|
58
|
+
also need to ensure that the three environment variables are set as
|
59
|
+
indicated above. If you're running in a development environment, you
|
60
|
+
can include these in your bash `~/.profile` file.
|
42
61
|
|
43
62
|
# Usage - Birst command line tool
|
44
63
|
|
@@ -130,6 +149,18 @@ The `spaces` variable is a Ruby hash parsed from the SOAP response.
|
|
130
149
|
The structure of the returned hash follows the structure that Birst
|
131
150
|
returns.
|
132
151
|
|
152
|
+
## Command arguments
|
153
|
+
|
154
|
+
Some Birst API commands require arguments. All arguments are supplied
|
155
|
+
as an argument hash. All arguments are mandatory even if they're blank/null
|
156
|
+
(Birst web API requirement). For example, to create a new space,
|
157
|
+
|
158
|
+
````ruby
|
159
|
+
Birst_Command::Session.start do |bc|
|
160
|
+
new_space_id = bc.create_new_space :spaceName => "myNewSpace", :comments => "Just testing",:automatic => "false"
|
161
|
+
end
|
162
|
+
````
|
163
|
+
|
133
164
|
## Cookies
|
134
165
|
|
135
166
|
The start session block can also accept an argument named `use_cookie` to
|
@@ -157,7 +188,8 @@ puts "COMPLETE? #{is_job_complete}"
|
|
157
188
|
## Helper methods
|
158
189
|
|
159
190
|
I find some of the Birst API responses to be rather cumbersome. For
|
160
|
-
example, why do I need hash with a single `user_space` key
|
191
|
+
example, why do I need hash with a single `user_space` key when I
|
192
|
+
run the `list_spaces` command? I'd
|
161
193
|
rather have an array of hashes here. To that end I find it convenient
|
162
194
|
to define helper methods that extend the Session class to simplify
|
163
195
|
some of this. To override the return value of the native
|
@@ -168,7 +200,7 @@ class Birst_Command::Session
|
|
168
200
|
def list_spaces(*args)
|
169
201
|
result = command __method__, *args
|
170
202
|
[result[:user_space]].flatten
|
171
|
-
end
|
203
|
+
end
|
172
204
|
end
|
173
205
|
````
|
174
206
|
|
@@ -181,17 +213,6 @@ gem because what I find helpful, you may not. Birst Command just
|
|
181
213
|
provides the basic interface.
|
182
214
|
|
183
215
|
|
184
|
-
## Command arguments
|
185
|
-
|
186
|
-
Some Birst API commands require arguments. All arguments are supplied
|
187
|
-
as an argument hash. For example, to create a new space,
|
188
|
-
|
189
|
-
````ruby
|
190
|
-
Birst_Command::Session.start do |bc|
|
191
|
-
new_space_id = bc.create_new_space :spaceName => "myNewSpace", :comments => "Just testing",:automatic => "false"
|
192
|
-
end
|
193
|
-
````
|
194
|
-
|
195
216
|
## camelCase/snake_case issues
|
196
217
|
|
197
218
|
Birst Command uses [Savon](http://savonrb.com/version2/client.html) as
|
@@ -206,4 +227,3 @@ entirely consistent in its use of camelCase for arguments (e.g.,
|
|
206
227
|
`listUsersInSpace`). This inconsistency requires us to **submit
|
207
228
|
commands as snake_case and arguments as the camelCase that Birst
|
208
229
|
uses.**
|
209
|
-
|
data/bin/birstcl
CHANGED
@@ -6,6 +6,24 @@ require "optparse"
|
|
6
6
|
module BirstCL
|
7
7
|
extend self
|
8
8
|
|
9
|
+
def run
|
10
|
+
set_options
|
11
|
+
|
12
|
+
if @options[:version]
|
13
|
+
puts "Birst_Command Version: #{Birst_Command::VERSION}"
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
if @options[:encrypt_password]
|
18
|
+
encrypt_password(@options[:encrypt_password])
|
19
|
+
end
|
20
|
+
|
21
|
+
if @options[:command]
|
22
|
+
read_config_file
|
23
|
+
execute_command
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
9
27
|
def set_options
|
10
28
|
@options = {}
|
11
29
|
|
@@ -26,6 +44,11 @@ module BirstCL
|
|
26
44
|
exit
|
27
45
|
end
|
28
46
|
|
47
|
+
@options[:encrypt_password] = nil
|
48
|
+
opts.on("-e","--encrypt_password <PASSWORD>","Generates an encrypted version of PASSWORD that needs to be placed in ~/.birstcl") do |opt|
|
49
|
+
@options[:encrypt_password] = opt
|
50
|
+
end
|
51
|
+
|
29
52
|
@options[:command] = nil
|
30
53
|
opts.on("-c","--command <COMMAND>","COMMAND is the snake_case Birst web API command") do |opt|
|
31
54
|
@options[:command] = opt
|
@@ -57,13 +80,7 @@ module BirstCL
|
|
57
80
|
opts.on("-r","--read_cookie_file <COOKIE FILE>", "Path to cookie file to read") do |opt|
|
58
81
|
@options[:read_cookie_full_path] = opt
|
59
82
|
end
|
60
|
-
|
61
83
|
end.parse!
|
62
|
-
|
63
|
-
if @options[:version]
|
64
|
-
puts "Birst_Command Version: #{Birst_Command::VERSION}"
|
65
|
-
exit
|
66
|
-
end
|
67
84
|
end
|
68
85
|
|
69
86
|
|
@@ -71,6 +88,14 @@ module BirstCL
|
|
71
88
|
Birst_Command::Config.read_config(@options[:config_full_path])
|
72
89
|
end
|
73
90
|
|
91
|
+
def encrypt_password(password)
|
92
|
+
Birst_Command::Password.generate_keys(verbose: true)
|
93
|
+
puts <<-EOF.unindent
|
94
|
+
...
|
95
|
+
Use this encrypted password in your .birstcl file: "#{Birst_Command::Password.encrypt(password)}"
|
96
|
+
EOF
|
97
|
+
end
|
98
|
+
|
74
99
|
|
75
100
|
def write_cookie_file(file_full_path)
|
76
101
|
return nil if file_full_path.nil?
|
@@ -100,6 +125,4 @@ module BirstCL
|
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
103
|
-
BirstCL.
|
104
|
-
BirstCL.read_config_file
|
105
|
-
BirstCL.execute_command
|
128
|
+
BirstCL.run
|
data/lib/birst_command.rb
CHANGED
@@ -2,10 +2,12 @@ require 'savon'
|
|
2
2
|
require 'httpclient'
|
3
3
|
require 'openssl'
|
4
4
|
require 'base64'
|
5
|
+
require 'securerandom'
|
5
6
|
require 'json'
|
6
7
|
|
7
8
|
require 'birst_command/config'
|
9
|
+
require 'birst_command/core_additions'
|
8
10
|
require 'birst_command/version'
|
9
|
-
require 'birst_command/
|
11
|
+
require 'birst_command/password'
|
10
12
|
require 'birst_command/session'
|
11
13
|
|
data/lib/birst_command/config.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Birst_Command
|
2
|
+
require 'erb'
|
2
3
|
module Config
|
3
4
|
extend self
|
4
5
|
|
@@ -12,7 +13,9 @@ module Birst_Command
|
|
12
13
|
}
|
13
14
|
|
14
15
|
def read_config(config_full_path = @config_full_path)
|
15
|
-
|
16
|
+
parse_erb = ERB.new(IO.read(config_full_path)).result(binding)
|
17
|
+
parse_json = JSON.parse(parse_erb, :symbolize_names => true)
|
18
|
+
@options = @options.merge!(parse_json)
|
16
19
|
end
|
17
20
|
|
18
21
|
def set_debug
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Birst_Command
|
2
|
+
module Password
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def generate_keys(verbose: false)
|
6
|
+
iv = ENV['BIRST_COMMAND_IV'] || SecureRandom.base64
|
7
|
+
key = ENV['BIRST_COMMAND_KEY'] || SecureRandom.base64(32)
|
8
|
+
salt = ENV['BIRST_COMMAND_SALT'] || SecureRandom.base64
|
9
|
+
|
10
|
+
if verbose
|
11
|
+
puts <<-EOF.unindent
|
12
|
+
Set these keys as environment variables
|
13
|
+
- Do not lose them or you will have to regenerate your password.
|
14
|
+
- Keep them secure, your password is compromised if these keys are compromised.
|
15
|
+
- Remove them as environment variables to generate new ones
|
16
|
+
BIRST_COMMAND_IV="#{iv}"
|
17
|
+
BIRST_COMMAND_KEY="#{key}"
|
18
|
+
BIRST_COMMAND_SALT="#{salt}"
|
19
|
+
EOF
|
20
|
+
end
|
21
|
+
|
22
|
+
ENV['BIRST_COMMAND_IV'] = iv
|
23
|
+
ENV['BIRST_COMMAND_KEY'] = key
|
24
|
+
ENV['BIRST_COMMAND_SALT'] = salt
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generate a new cipher for encryption or decryption
|
28
|
+
def create_cipher(mode)
|
29
|
+
iv = ENV['BIRST_COMMAND_IV'] || SecureRandom.base64
|
30
|
+
key = ENV['BIRST_COMMAND_KEY'] || SecureRandom.base64(32)
|
31
|
+
salt = ENV['BIRST_COMMAND_SALT'] || SecureRandom.base64
|
32
|
+
|
33
|
+
cipher = OpenSSL::Cipher.new 'AES-128-CBC'
|
34
|
+
cipher.send(mode)
|
35
|
+
cipher.iv = iv
|
36
|
+
|
37
|
+
digest = OpenSSL::Digest::SHA256.new
|
38
|
+
key_len = cipher.key_len
|
39
|
+
iter = 20000
|
40
|
+
cipher.key = OpenSSL::PKCS5.pbkdf2_hmac(key, salt, iter, key_len, digest)
|
41
|
+
cipher
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Returns a base64-obfuscated password to be stored in the config.json file
|
46
|
+
def encrypt(pwd)
|
47
|
+
cipher = create_cipher(:encrypt)
|
48
|
+
|
49
|
+
encrypted = cipher.update pwd
|
50
|
+
encrypted << cipher.final
|
51
|
+
|
52
|
+
Base64.encode64(encrypted).chomp
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Returns a plaintext password
|
57
|
+
def decrypt(encrypted_pwd)
|
58
|
+
cipher = create_cipher(:decrypt)
|
59
|
+
|
60
|
+
decrypted = cipher.update Base64.decode64(encrypted_pwd)
|
61
|
+
decrypted << cipher.final
|
62
|
+
|
63
|
+
decrypted
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -39,7 +39,7 @@ module Birst_Command
|
|
39
39
|
cookies: @auth_cookies,
|
40
40
|
message: {
|
41
41
|
username: @options[:username],
|
42
|
-
password:
|
42
|
+
password: Password.decrypt(@options[:password])
|
43
43
|
})
|
44
44
|
|
45
45
|
@auth_cookies = @response.http.cookies if @auth_cookies.nil?
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "test_birst_command"
|
2
|
+
|
3
|
+
class Test_password < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
ENV['BIRST_COMMAND_IV'] = "3Ez9fL0Jlt/E1d7QlVtKdw=="
|
7
|
+
ENV['BIRST_COMMAND_KEY'] = "N589Xi0YzzkE+bRGwp3yaoVk/lneYsLHdFP+366hwcY="
|
8
|
+
ENV['BIRST_COMMAND_SALT'] = "AUkJj8QSmNW3QazpyNl7og=="
|
9
|
+
|
10
|
+
@password = "mysecretpass"
|
11
|
+
@encrypted = "dP5+BfQyTAvKOM6s1ik4zg=="
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_key_generation
|
18
|
+
ENV['BIRST_COMMAND_IV'] = nil
|
19
|
+
ENV['BIRST_COMMAND_KEY'] = nil
|
20
|
+
ENV['BIRST_COMMAND_SALT'] = nil
|
21
|
+
|
22
|
+
Password.generate_keys
|
23
|
+
|
24
|
+
encrypted = Password.encrypt(@password)
|
25
|
+
decrypted = Password.decrypt(encrypted)
|
26
|
+
|
27
|
+
assert_equal @password, decrypted, "Wrong decrypted password"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def test_decryption_failure
|
32
|
+
Password.generate_keys
|
33
|
+
|
34
|
+
encrypted = Password.encrypt(@password)
|
35
|
+
ENV['BIRST_COMMAND_SALT'] = SecureRandom.base64
|
36
|
+
|
37
|
+
assert_raise OpenSSL::Cipher::CipherError do
|
38
|
+
decrypted = Password.decrypt(encrypted)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def test_encrypt
|
44
|
+
assert_equal @encrypted, Password.encrypt(@password), "Expecting encrypted password #{@encrypted}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_decrypt
|
48
|
+
assert_equal @password, Password.decrypt(@encrypted), "Expecting decrypted password #{@password}"
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Birst_Command
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sterling Paramore
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: savon
|
@@ -43,7 +43,6 @@ email:
|
|
43
43
|
- gnilrets@gmail.com
|
44
44
|
executables:
|
45
45
|
- birstcl
|
46
|
-
- obfuscate_pwd.rb
|
47
46
|
extensions: []
|
48
47
|
extra_rdoc_files: []
|
49
48
|
files:
|
@@ -56,12 +55,12 @@ files:
|
|
56
55
|
- README.md
|
57
56
|
- Rakefile
|
58
57
|
- bin/birstcl
|
59
|
-
- bin/obfuscate_pwd.rb
|
60
58
|
- config.json_template
|
61
59
|
- doc/roadmap.md
|
62
60
|
- lib/birst_command.rb
|
63
61
|
- lib/birst_command/config.rb
|
64
|
-
- lib/birst_command/
|
62
|
+
- lib/birst_command/core_additions.rb
|
63
|
+
- lib/birst_command/password.rb
|
65
64
|
- lib/birst_command/session.rb
|
66
65
|
- lib/birst_command/version.rb
|
67
66
|
- test/.gitignore
|
@@ -71,9 +70,9 @@ files:
|
|
71
70
|
- test/standard/test_command_helper.rb
|
72
71
|
- test/standard/test_cookie.rb
|
73
72
|
- test/standard/test_copy_space.rb
|
74
|
-
- test/standard/test_deobfuscate.rb
|
75
73
|
- test/standard/test_list_spaces.rb
|
76
74
|
- test/standard/test_login.rb
|
75
|
+
- test/standard/test_password.rb
|
77
76
|
- test/standard/test_read_config.rb
|
78
77
|
- test/test_birst_command.rb
|
79
78
|
homepage: https://github.com/gnilrets
|
@@ -107,8 +106,8 @@ test_files:
|
|
107
106
|
- test/standard/test_command_helper.rb
|
108
107
|
- test/standard/test_cookie.rb
|
109
108
|
- test/standard/test_copy_space.rb
|
110
|
-
- test/standard/test_deobfuscate.rb
|
111
109
|
- test/standard/test_list_spaces.rb
|
112
110
|
- test/standard/test_login.rb
|
111
|
+
- test/standard/test_password.rb
|
113
112
|
- test/standard/test_read_config.rb
|
114
113
|
- test/test_birst_command.rb
|
data/bin/obfuscate_pwd.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
module Birst_Command
|
2
|
-
module Obfuscate
|
3
|
-
extend self
|
4
|
-
|
5
|
-
@crypt_pwd = "BirstIsAwesome"
|
6
|
-
@salt = "31415927"
|
7
|
-
@cypher = "AES-128-CBC"
|
8
|
-
|
9
|
-
def obfuscate(pwd)
|
10
|
-
# Returns a base64-obfuscated password to be stored in the config.json file
|
11
|
-
encrypter = OpenSSL::Cipher::Cipher.new @cypher
|
12
|
-
encrypter.encrypt
|
13
|
-
encrypter.pkcs5_keyivgen @crypt_pwd, @salt
|
14
|
-
|
15
|
-
encrypted = encrypter.update pwd
|
16
|
-
encrypted << encrypter.final
|
17
|
-
|
18
|
-
Base64.encode64(encrypted).chomp
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def deobfuscate(obfuscated_pwd)
|
23
|
-
# Returns a plaintext password
|
24
|
-
decrypter = OpenSSL::Cipher::Cipher.new @cypher
|
25
|
-
decrypter.decrypt
|
26
|
-
decrypter.pkcs5_keyivgen @crypt_pwd, @salt
|
27
|
-
|
28
|
-
plain = decrypter.update Base64.decode64(obfuscated_pwd)
|
29
|
-
plain << decrypter.final
|
30
|
-
|
31
|
-
plain
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require "test_birst_command"
|
2
|
-
|
3
|
-
class Test_deobfuscate < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def setup
|
6
|
-
@pwd = "mysecretpass"
|
7
|
-
@obs_pwd = "IQX4os6wCE7rl+JuSYL2Iw=="
|
8
|
-
end
|
9
|
-
|
10
|
-
def teardown
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_obfuscate
|
14
|
-
assert_equal @obs_pwd, Obfuscate.obfuscate(@pwd), "Expecting password #{@obs_pwd}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_deobfuscate
|
18
|
-
assert_equal @pwd, Obfuscate.deobfuscate(@obs_pwd), "Expecting password #{@pwd}"
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
|