zanzibar 0.1.9 → 0.1.10

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MGVkMGM2YjU2MjA3YTAyZjQ2NDBkZTUxNjkzZTdhZDk1NGFmMjdmZg==
4
+ Y2NmMTgxMGFhODNjYWQ4MWNmNjY3MWFjZWZiMGYyZjIzMzgwYzc1Yw==
5
5
  data.tar.gz: !binary |-
6
- OGVkZTA1ZjljMjVkYTA1MzMwMTRiODIzYmM1NzBiODQzMmRiMWU1OQ==
6
+ ZDZhYThhNTk3MTk4MTc1MzJjYjlhMDQzMzI1YmI1Yjc3MTZlNDJkZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MmJhMzQ3NDczMTU0YWQyNTIwODJmNjAzNzg4MDBjY2M3NDM3ODY2N2MwOGY4
10
- MWE1NTMwNjBlYmIyYTdmMGM3NDBkNjg5MzE0N2I5YTJmMjAzOTFjNmRlZWI5
11
- MTE2YjJjY2IzOTViMzhkNDEwOTllMDE1MzFkN2NhODBkMzc3MmU=
9
+ Y2Y3NDM5M2E3MDM3NTZkOGE4OWQ0YTZkZThhNmMxNjcxNzU3MjcwNTEzYzAw
10
+ MWNlNGY3MTdmODdjZGIxY2VjMzliM2JlYzJlYTZjMzQ1YTBmYTkxYzZjYmNi
11
+ ZDIzNzIzZGEwNWQwMDczMjVjY2JkOTE1Nzk5N2RmM2MzODIxNDE=
12
12
  data.tar.gz: !binary |-
13
- YjMwMjI1YzhkOThjN2FhMGFjZjYyZjY4MmJmODY2MmU1NzY5MjU2NGJmMjBi
14
- ZTAwYmQ3NWY5OGU4NzQxMjZiZjkyOWVkMGI0MmFkNDg4NGEwOWJlNGJhODk2
15
- Zjc2NjUyYmE0MDk1YjM2YzZiZDFjOTA4MzQ0OTJmZWJlMGMzN2U=
13
+ ZGFkNDI2NDNlMjBiZDI4ZjYzNDdlMzZkMmE4ZGI1NDc4MTk0ZjRmODMyZWU5
14
+ NDdhOTg4NjA3YTNiMDg1MDhlYjRhMWVkODI3NzM1NTc4MmQ0MGMyNDM4OGJk
15
+ YjA3YzVmODI5YzkxZDU0NzMyYzM5MDQ2NTcxNTg1YmVlY2FlZTk=
data/lib/zanzibar.rb CHANGED
@@ -1,210 +1,188 @@
1
- require "zanzibar/version"
2
- require 'savon'
3
- require 'io/console'
4
- require 'fileutils'
5
-
6
- module Zanzibar
7
-
8
- ##
9
- # Class for interacting with Secret Server
10
- class Zanzibar
11
-
12
- ##
13
- # @param args{:domain, :wsdl, :pwd, :username, :globals{}}
14
-
15
- def initialize(args = {})
16
-
17
- if args[:username]
18
- @@username = args[:username]
19
- else
20
- @@username = ENV['USER']
21
- end
22
-
23
- if args[:wsdl]
24
- @@wsdl = args[:wsdl]
25
- else
26
- @@wsdl = get_wsdl_location
27
- end
28
- if args[:pwd]
29
- @@password = args[:pwd]
30
- else
31
- @@password = prompt_for_password
32
- end
33
- if args[:domain]
34
- @@domain = args[:domain]
35
- else
36
- @@domain = prompt_for_domain
37
- end
38
- args[:globals] = {} unless args[:globals]
39
- init_client(args[:globals])
40
- end
41
-
42
- ## Initializes the Savon client class variable with the wdsl document location and optional global variables
43
- # @param globals{}, optional
44
-
45
- def init_client(globals = {})
46
- globals = {} if globals == nil
47
- @@client = Savon.client(globals) do
48
- wsdl @@wsdl
49
- end
50
- end
51
-
52
- ## Gets the user's password if none is provided in the constructor.
53
- # @return [String] the password for the current user
54
-
55
- def prompt_for_password
56
- puts "Please enter password for #{@@username}:"
57
- return STDIN.noecho(&:gets).chomp
58
- end
59
-
60
- ## Gets the wsdl document location if none is provided in the constructor
61
- # @return [String] the location of the WDSL document
62
-
63
- def get_wsdl_location
64
- puts "Enter the URL of the Secret Server WSDL:"
65
- return STDIN.gets.chomp
66
- end
67
-
68
- ## Gets the domain of the Secret Server installation if none is provided in the constructor
69
- # @return [String] the domain of the secret server installation
70
-
71
- def prompt_for_domain
72
- puts "Enter the domain of your Secret Server:"
73
- return STDIN.gets.chomp
74
- end
75
-
76
-
77
- ## Get an authentication token for interacting with Secret Server. These are only good for about 10 minutes so just get a new one each time.
78
- # Will raise an error if there is an issue with the authentication.
79
- # @return the authentication token for the current user.
80
-
81
- def get_token
82
- begin
83
- response = @@client.call(:authenticate, message: { username: @@username, password: @@password, organization: "", domain: @@domain }).hash
84
- if response[:envelope][:body][:authenticate_response][:authenticate_result][:errors]
85
- raise "Error generating the authentication token for user #{@@username}: #{response[:envelope][:body][:authenticate_response][:authenticate_result][:errors][:string]}"
86
- end
87
- response[:envelope][:body][:authenticate_response][:authenticate_result][:token]
88
- rescue Savon::Error => err
89
- raise "There was an error generating the authentiaton token for user #{@@username}: #{err}"
90
- end
91
- end
92
-
93
- ## Get a secret returned as a hash
94
- # Will raise an error if there was an issue getting the secret
95
- # @param [Integer] the secret id
96
- # @return [Hash] the secret hash retrieved from the wsdl
97
-
98
- def get_secret(scrt_id, token = nil)
99
- begin
100
- secret = @@client.call(:get_secret, message: { token: token || get_token, secretId: scrt_id}).hash
101
- if secret[:envelope][:body][:get_secret_response][:get_secret_result][:errors]
102
- raise "There was an error getting secret #{scrt_id}: #{secret[:envelope][:body][:get_secret_response][:get_secret_result][:errors][:string]}"
103
- end
104
- return secret
105
- rescue Savon::Error => err
106
- raise "There was an error getting the secret with id #{scrt_id}: #{err}"
107
- end
108
- end
109
-
110
- ## Retrieve a simple password from a secret
111
- # Will raise an error if there are any issues
112
- # @param [Integer] the secret id
113
- # @return [String] the password for the given secret
114
-
115
- def get_password(scrt_id)
116
- begin
117
- secret = get_secret(scrt_id)
118
- secret_items = secret[:envelope][:body][:get_secret_response][:get_secret_result][:secret][:items][:secret_item]
119
- return get_secret_item_by_field_name(secret_items,"Password")[:value]
120
- rescue Savon::Error => err
121
- raise "There was an error getting the password for secret #{scrt_id}: #{err}"
122
- end
123
- end
124
-
125
- def get_secret_item_by_field_name(secret_items, field_name)
126
- secret_items.each do |item|
127
- return item if item[:field_name] == field_name
128
- end
129
- end
130
-
131
- ## Get the secret item id that relates to a key file or attachment.
132
- # Will raise on error
133
- # @param [Integer] the secret id
134
- # @param [String] the type of secret item to get, one of privatekey, publickey, attachment
135
- # @return [Integer] the secret item id
136
-
137
- def get_scrt_item_id(scrt_id, type, token)
138
- secret = get_secret(scrt_id, token)
139
- secret_items = secret[:envelope][:body][:get_secret_response][:get_secret_result][:secret][:items][:secret_item]
140
- begin
141
- return get_secret_item_by_field_name(secret_items, type)[:id]
142
- rescue
143
- raise "Unknown type, #{type}."
144
- end
145
- end
146
-
147
- ## Downloads the private key for a secret and places it where Zanzibar is running, or :path if specified
148
- # Raise on error
149
- # @param [Hash] args, :scrt_id, :scrt_item_id - optional, :path - optional
150
-
151
- def download_private_key(args = {})
152
- token = get_token
153
- FileUtils.mkdir_p(args[:path]) if args[:path]
154
- path = args[:path] ? args[:path] : '.' ## The File.join below doesn't handle nils well, so let's take that possibility away.
155
- begin
156
- response = @@client.call(:download_file_attachment_by_item_id, message: { token: token, secretId: args[:scrt_id], secretItemId: args[:scrt_item_id] || get_scrt_item_id(args[:scrt_id], 'Private Key', token)}).hash
157
- if response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:errors]
158
- raise "There was an error getting the private key for secret #{args[:scrt_id]}: #{response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:string]}"
159
- end
160
- File.open(File.join(path, response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_name]), 'wb') do |file|
161
- file.puts Base64.decode64(response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_attachment])
162
- end
163
- rescue Savon::Error => err
164
- raise "There was an error getting the private key for secret #{args[:scrt_id]}: #{err}"
165
- end
166
- end
167
-
168
- ## Downloads the public key for a secret and places it where Zanzibar is running, or :path if specified
169
- # Raise on error
170
- # @param [Hash] args, :scrt_id, :scrt_item_id - optional, :path - optional
171
-
172
- def download_public_key(args = {})
173
- token = get_token
174
- FileUtils.mkdir_p(args[:path]) if args[:path]
175
- path = args[:path] ? args[:path] : '.' ## The File.join below doesn't handle nils well, so let's take that possibility away.
176
- begin
177
- response = @@client.call(:download_file_attachment_by_item_id, message: { token: token, secretId: args[:scrt_id], secretItemId: args[:scrt_item_id] || get_scrt_item_id(args[:scrt_id], 'Public Key', token)}).hash
178
- if response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:errors]
179
- raise "There was an error getting the public key for secret #{args[:scrt_id]}: #{response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:string]}"
180
- end
181
- File.open(File.join(path, response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_name]), 'wb') do |file|
182
- file.puts Base64.decode64(response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_attachment])
183
- end
184
- rescue Savon::Error => err
185
- raise "There was an error getting the public key for secret #{args[:scrt_id]}: #{err}"
186
- end
187
- end
188
-
189
- ## Downloads an attachment for a secret and places it where Zanzibar is running, or :path if specified
190
- # Raise on error
191
- # @param [Hash] args, :scrt_id, :scrt_item_id - optional, :path - optional
192
-
193
- def download_attachment(args = {})
194
- token = get_token
195
- FileUtils.mkdir_p(args[:path]) if args[:path]
196
- path = args[:path] ? args[:path] : '.' ## The File.join below doesn't handle nils well, so let's take that possibility away.
197
- begin
198
- response = @@client.call(:download_file_attachment_by_item_id, message: { token: token, secretId: args[:scrt_id], secretItemId: args[:scrt_item_id] || get_scrt_item_id(args[:scrt_id], 'Attachment', token)}).hash
199
- if response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:errors]
200
- raise "There was an error getting the attachment for secret #{args[:scrt_id]}: #{response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:string]}"
201
- end
202
- File.open(File.join(path, response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_name]), 'wb') do |file|
203
- file.puts Base64.decode64(response[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result][:file_attachment])
204
- end
205
- rescue Savon::Error => err
206
- raise "There was an error getting the attachment from secret #{args[:scrt_id]}: #{err}"
207
- end
208
- end
209
- end
210
- end
1
+ require "zanzibar/version"
2
+ require 'savon'
3
+ require 'io/console'
4
+ require 'fileutils'
5
+
6
+ module Zanzibar
7
+
8
+ ##
9
+ # Class for interacting with Secret Server
10
+ class Zanzibar
11
+
12
+ ##
13
+ # @param args{:domain, :wsdl, :pwd, :username, :globals{}}
14
+
15
+ def initialize(args = {})
16
+
17
+ if args[:username]
18
+ @@username = args[:username]
19
+ else
20
+ @@username = ENV['USER']
21
+ end
22
+
23
+ if args[:wsdl]
24
+ @@wsdl = args[:wsdl]
25
+ else
26
+ @@wsdl = get_wsdl_location
27
+ end
28
+ if args[:pwd]
29
+ @@password = args[:pwd]
30
+ else
31
+ @@password = prompt_for_password
32
+ end
33
+ if args[:domain]
34
+ @@domain = args[:domain]
35
+ else
36
+ @@domain = prompt_for_domain
37
+ end
38
+ args[:globals] = {} unless args[:globals]
39
+ init_client(args[:globals])
40
+ end
41
+
42
+ ## Initializes the Savon client class variable with the wdsl document location and optional global variables
43
+ # @param globals{}, optional
44
+
45
+ def init_client(globals = {})
46
+ globals = {} if globals == nil
47
+ @@client = Savon.client(globals) do
48
+ wsdl @@wsdl
49
+ end
50
+ end
51
+
52
+ ## Gets the user's password if none is provided in the constructor.
53
+ # @return [String] the password for the current user
54
+
55
+ def prompt_for_password
56
+ puts "Please enter password for #{@@username}:"
57
+ return STDIN.noecho(&:gets).chomp
58
+ end
59
+
60
+ ## Gets the wsdl document location if none is provided in the constructor
61
+ # @return [String] the location of the WDSL document
62
+
63
+ def prompt_for_wsdl_location
64
+ puts "Enter the URL of the Secret Server WSDL:"
65
+ return STDIN.gets.chomp
66
+ end
67
+
68
+ ## Gets the domain of the Secret Server installation if none is provided in the constructor
69
+ # @return [String] the domain of the secret server installation
70
+
71
+ def prompt_for_domain
72
+ puts "Enter the domain of your Secret Server:"
73
+ return STDIN.gets.chomp
74
+ end
75
+
76
+
77
+ ## Get an authentication token for interacting with Secret Server. These are only good for about 10 minutes so just get a new one each time.
78
+ # Will raise an error if there is an issue with the authentication.
79
+ # @return the authentication token for the current user.
80
+
81
+ def get_token
82
+ begin
83
+ response = @@client.call(:authenticate, message: { username: @@username, password: @@password, organization: "", domain: @@domain })
84
+ .hash[:envelope][:body][:authenticate_response][:authenticate_result]
85
+ raise "Error generating the authentication token for user #{@@username}: #{response[:errors][:string]}" if response[:errors]
86
+ response[:token]
87
+ rescue Savon::Error => err
88
+ raise "There was an error generating the authentiaton token for user #{@@username}: #{err}"
89
+ end
90
+ end
91
+
92
+ ## Get a secret returned as a hash
93
+ # Will raise an error if there was an issue getting the secret
94
+ # @param [Integer] the secret id
95
+ # @return [Hash] the secret hash retrieved from the wsdl
96
+
97
+ def get_secret(scrt_id, token = nil)
98
+ begin
99
+ secret = @@client.call(:get_secret, message: { token: token || get_token, secretId: scrt_id}).hash[:envelope][:body][:get_secret_response][:get_secret_result]
100
+ raise "There was an error getting secret #{scrt_id}: #{secret[:errors][:string]}" if secret[:errors]
101
+ return secret
102
+ rescue Savon::Error => err
103
+ raise "There was an error getting the secret with id #{scrt_id}: #{err}"
104
+ end
105
+ end
106
+
107
+ ## Retrieve a simple password from a secret
108
+ # Will raise an error if there are any issues
109
+ # @param [Integer] the secret id
110
+ # @return [String] the password for the given secret
111
+
112
+ def get_password(scrt_id)
113
+ begin
114
+ secret = get_secret(scrt_id)
115
+ secret_items = secret[:secret][:items][:secret_item]
116
+ return get_secret_item_by_field_name(secret_items,"Password")[:value]
117
+ rescue Savon::Error => err
118
+ raise "There was an error getting the password for secret #{scrt_id}: #{err}"
119
+ end
120
+ end
121
+
122
+ def write_secret_to_file(path, secret_response)
123
+ File.open(File.join(path, secret_response[:file_name]), 'wb') do |file|
124
+ file.puts Base64.decode64(secret_response[:file_attachment])
125
+ end
126
+ end
127
+
128
+ def get_secret_item_by_field_name(secret_items, field_name)
129
+ secret_items.each do |item|
130
+ return item if item[:field_name] == field_name
131
+ end
132
+ end
133
+
134
+ ## Get the secret item id that relates to a key file or attachment.
135
+ # Will raise on error
136
+ # @param [Integer] the secret id
137
+ # @param [String] the type of secret item to get, one of privatekey, publickey, attachment
138
+ # @return [Integer] the secret item id
139
+
140
+ def get_scrt_item_id(scrt_id, type, token)
141
+ secret = get_secret(scrt_id, token)
142
+ secret_items = secret[:secret][:items][:secret_item]
143
+ begin
144
+ return get_secret_item_by_field_name(secret_items, type)[:id]
145
+ rescue
146
+ raise "Unknown type, #{type}."
147
+ end
148
+ end
149
+
150
+ ## Downloads a file for a secret and places it where Zanzibar is running, or :path if specified
151
+ # Raise on error
152
+ # @param [Hash] args, :scrt_id, :type (one of "Private Key", "Public Key", "Attachment"), :scrt_item_id - optional, :path - optional
153
+
154
+
155
+ def download_secret_file(args = {})
156
+ token = get_token
157
+ FileUtils.mkdir_p(args[:path]) if args[:path]
158
+ path = args[:path] ? args[:path] : '.' ## The File.join below doesn't handle nils well, so let's take that possibility away.
159
+ begin
160
+ response = @@client.call(:download_file_attachment_by_item_id, message:
161
+ { token: token, secretId: args[:scrt_id], secretItemId: args[:scrt_item_id] || get_scrt_item_id(args[:scrt_id], args[:type], token)})
162
+ .hash[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result]
163
+ raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{response[:errors][:string]}" if response[:errors]
164
+ write_secret_to_file(path, response)
165
+ rescue Savon::Error => err
166
+ raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{err}"
167
+ end
168
+ end
169
+
170
+
171
+ ## Methods to maintain backwards compatibility
172
+ def download_private_key(args = {})
173
+ args[:type] = 'Private Key'
174
+ download_secret_file(args)
175
+ end
176
+
177
+ def download_public_key(args = {})
178
+ args[:type] = 'Public Key'
179
+ download_secret_file(args)
180
+ end
181
+
182
+ def download_attachment(args = {})
183
+ args[:type] = 'Attachment'
184
+ download_secret_file(args)
185
+ end
186
+
187
+ end
188
+ end
@@ -1,3 +1,3 @@
1
1
  module Zanzibar
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
@@ -30,7 +30,7 @@ describe "Zanzibar Test" do
30
30
  to_return(:body => auth_xml, :status => 200).then.
31
31
  to_return(:body => secret_xml, :status => 200)
32
32
 
33
- expect(client.get_secret(1234)[:envelope][:body][:get_secret_response][:get_secret_result][:secret][:name]).to eq("Zanzi Test Secret")
33
+ expect(client.get_secret(1234)[:secret][:name]).to eq("Zanzi Test Secret")
34
34
  end
35
35
 
36
36
  it 'should get a password' do
@@ -47,12 +47,24 @@ describe "Zanzibar Test" do
47
47
  to_return(:body => secret_with_key_xml, :status => 200).then.
48
48
  to_return(:body => private_key_xml, :status => 200)
49
49
 
50
- client.download_private_key(:scrt_id => 2345)
50
+ client.download_secret_file(:scrt_id => 2345, :type => 'Private Key')
51
51
  expect(File.exist? 'zanzi_key')
52
52
  expect(File.read('zanzi_key')).to eq("-----BEGIN RSA PRIVATE KEY -----\nzanzibarTestPassword\n-----END RSA PRIVATE KEY-----\n")
53
53
  File.delete('zanzi_key')
54
54
  end
55
55
 
56
+ it 'should download a private key legacy' do
57
+ stub_request(:any, "https://www.zanzitest.net/webservices/sswebservice.asmx").
58
+ to_return(:body => auth_xml, :status => 200).then.
59
+ to_return(:body => secret_with_key_xml, :status => 200).then.
60
+ to_return(:body => private_key_xml, :status => 200)
61
+
62
+ client.download_private_key(:scrt_id => 2345)
63
+ expect(File.exist? 'zanzi_key')
64
+ expect(File.read('zanzi_key')).to eq("-----BEGIN RSA PRIVATE KEY -----\nzanzibarTestPassword\n-----END RSA PRIVATE KEY-----\n")
65
+ File.delete('zanzi_key')
66
+ end
67
+
56
68
 
57
69
  it 'should download a public key' do
58
70
  stub_request(:any, "https://www.zanzitest.net/webservices/sswebservice.asmx").
@@ -60,18 +72,42 @@ describe "Zanzibar Test" do
60
72
  to_return(:body => secret_with_key_xml, :status => 200).then.
61
73
  to_return(:body => public_key_xml, :status => 200)
62
74
 
63
- client.download_public_key(:scrt_id => 2345)
75
+ client.download_secret_file(:scrt_id => 2345, :type => 'Public Key')
64
76
  expect(File.exist? 'zanzi_key.pub')
65
77
  expect(File.read('zanzi_key.pub')).to eq("1234PublicKey5678==\n")
66
78
  File.delete('zanzi_key.pub')
67
79
  end
68
80
 
81
+ it 'should download a public key legacy' do
82
+ stub_request(:any, "https://www.zanzitest.net/webservices/sswebservice.asmx").
83
+ to_return(:body => auth_xml, :status => 200).then.
84
+ to_return(:body => secret_with_key_xml, :status => 200).then.
85
+ to_return(:body => public_key_xml, :status => 200)
86
+
87
+ client.download_public_key(:scrt_id => 2345)
88
+ expect(File.exist? 'zanzi_key.pub')
89
+ expect(File.read('zanzi_key.pub')).to eq("1234PublicKey5678==\n")
90
+ File.delete('zanzi_key.pub')
91
+ end
92
+
69
93
  it 'should download an attachment' do
70
94
  stub_request(:any, "https://www.zanzitest.net/webservices/sswebservice.asmx").
71
95
  to_return(:body => auth_xml, :status => 200).then.
72
96
  to_return(:body => secret_with_attachment_xml, :status => 200).then.
73
97
  to_return(:body => attachment_xml, :status => 200)
74
98
 
99
+ client.download_secret_file(:scrt_id => 3456, :type => 'Attachment')
100
+ expect(File.exist? 'attachment.txt')
101
+ expect(File.read('attachment.txt')).to eq("I am a secret attachment\n")
102
+ File.delete('attachment.txt')
103
+ end
104
+
105
+ it 'should download an attachment legacy' do
106
+ stub_request(:any, "https://www.zanzitest.net/webservices/sswebservice.asmx").
107
+ to_return(:body => auth_xml, :status => 200).then.
108
+ to_return(:body => secret_with_attachment_xml, :status => 200).then.
109
+ to_return(:body => attachment_xml, :status => 200)
110
+
75
111
  client.download_attachment(:scrt_id => 3456)
76
112
  expect(File.exist? 'attachment.txt')
77
113
  expect(File.read('attachment.txt')).to eq("I am a secret attachment\n")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zanzibar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Davis-Cooke