mixlib-authentication 2.0.0 → 3.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
3
-
4
- group(:development) do
5
- gem "pry"
6
- gem "mixlib-log", '~> 2'
7
- end
data/NOTICE DELETED
@@ -1,7 +0,0 @@
1
- Mixlib::Authentication NOTICE
2
- =================
3
-
4
- Developed at Chef (https://www.chef.io/).
5
-
6
- * Copyright 2009-2016, Chef Software, Inc. <legal@chef.io>
7
-
data/README.md DELETED
@@ -1,23 +0,0 @@
1
- # Mixlib::Authentication
2
- [![Build Status Master](https://travis-ci.org/chef/mixlib-authentication.svg?branch=master)](https://travis-ci.org/chef/mixlib-authentication) [![Gem Version](https://badge.fury.io/rb/mixlib-authentication.svg)](https://badge.fury.io/rb/mixlib-authentication)
3
-
4
- Mixlib::Authentication provides a class-based header signing authentication object, like the one used in Chef.
5
-
6
- ## License
7
- - Author:: Christopher Brown ([cb@chef.io](mailto:cb@chef.io))
8
- - Copyright:: Copyright (c) 2009-2016 Chef Software, Inc.
9
- - License:: Apache License, Version 2.0
10
-
11
- ```text
12
- Licensed under the Apache License, Version 2.0 (the "License");
13
- you may not use this file except in compliance with the License.
14
- You may obtain a copy of the License at
15
-
16
- http://www.apache.org/licenses/LICENSE-2.0
17
-
18
- Unless required by applicable law or agreed to in writing, software
19
- distributed under the License is distributed on an "AS IS" BASIS,
20
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
- See the License for the specific language governing permissions and
22
- limitations under the License.
23
- ```
data/Rakefile DELETED
@@ -1,18 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
7
-
8
- begin
9
- require "chefstyle"
10
- require "rubocop/rake_task"
11
- RuboCop::RakeTask.new(:style) do |task|
12
- task.options += ["--display-cop-names", "--no-color"]
13
- end
14
- rescue LoadError
15
- puts "chefstyle/rubocop is not available."
16
- end
17
-
18
- task :ci => [:style, :spec]
@@ -1,22 +0,0 @@
1
- $:.unshift(File.dirname(__FILE__) + "/lib")
2
- require "mixlib/authentication/version"
3
-
4
- Gem::Specification.new do |s|
5
- s.name = "mixlib-authentication"
6
- s.version = Mixlib::Authentication::VERSION
7
- s.platform = Gem::Platform::RUBY
8
- s.summary = "Mixes in simple per-request authentication"
9
- s.description = s.summary
10
- s.license = "Apache-2.0"
11
- s.author = "Chef Software, Inc."
12
- s.email = "info@chef.io"
13
- s.homepage = "https://www.chef.io"
14
-
15
- s.require_path = "lib"
16
- s.files = %w{LICENSE README.md Gemfile Rakefile NOTICE} + Dir.glob("*.gemspec") +
17
- Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
18
-
19
- %w{rspec-core rspec-expectations rspec-mocks}.each { |gem| s.add_development_dependency gem, "~> 3.2" }
20
- s.add_development_dependency "chefstyle"
21
- s.add_development_dependency "rake", "~> 11"
22
- end
@@ -1,24 +0,0 @@
1
- require "mixlib/authentication/digester"
2
-
3
- describe Mixlib::Authentication::Digester do
4
- context "backcompat" do
5
- # The digester API should really have been private,
6
- # however oc-chef-pedant uses it.
7
- let(:test_string) { "hello" }
8
- let(:test_string_checksum) { "qvTGHdzF6KLavt4PO0gs2a6pQ00=" }
9
-
10
- describe "#hash_file" do
11
- it "should default to use SHA1" do
12
- expect(described_class.hash_file(StringIO.new(test_string))).to(
13
- eq(test_string_checksum))
14
- end
15
- end
16
-
17
- describe "#hash_string" do
18
- it "should default to use SHA1" do
19
- expect(described_class.hash_string(test_string)).to(
20
- eq(test_string_checksum))
21
- end
22
- end
23
- end
24
- end
@@ -1,132 +0,0 @@
1
- # Author:: Daniel DeLeo (<dan@opscode.com>)
2
- # Copyright:: Copyright (c) 2010 Opscode, Inc.
3
- # License:: Apache License, Version 2.0
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
- #
17
-
18
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
19
-
20
- require "mixlib/authentication"
21
- require "mixlib/authentication/http_authentication_request"
22
- require "ostruct"
23
- require "pp"
24
-
25
- describe Mixlib::Authentication::HTTPAuthenticationRequest do
26
- before do
27
- request = Struct.new(:env, :method, :path)
28
-
29
- @timestamp_iso8601 = "2009-01-01T12:00:00Z"
30
- @x_ops_content_hash = "DFteJZPVv6WKdQmMqZUQUumUyRs="
31
- @user_id = "spec-user"
32
- @http_x_ops_lines = [
33
- "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4",
34
- "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
35
- "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
36
- "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
37
- "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0",
38
- "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w=="]
39
- @merb_headers = {
40
- # These are used by signatureverification. An arbitrary sampling of non-HTTP_*
41
- # headers are in here to exercise that code path.
42
- "HTTP_HOST" => "127.0.0.1",
43
- "HTTP_X_OPS_SIGN" => "version=1.0",
44
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
45
- "HTTP_X_OPS_TIMESTAMP" => @timestamp_iso8601,
46
- "HTTP_X_OPS_CONTENT_HASH" => @x_ops_content_hash,
47
- "HTTP_X_OPS_USERID" => @user_id,
48
- "HTTP_X_OPS_AUTHORIZATION_1" => @http_x_ops_lines[0],
49
- "HTTP_X_OPS_AUTHORIZATION_2" => @http_x_ops_lines[1],
50
- "HTTP_X_OPS_AUTHORIZATION_3" => @http_x_ops_lines[2],
51
- "HTTP_X_OPS_AUTHORIZATION_4" => @http_x_ops_lines[3],
52
- "HTTP_X_OPS_AUTHORIZATION_5" => @http_x_ops_lines[4],
53
- "HTTP_X_OPS_AUTHORIZATION_6" => @http_x_ops_lines[5],
54
-
55
- # Random sampling
56
- "REMOTE_ADDR" => "127.0.0.1",
57
- "PATH_INFO" => "/organizations/local-test-org/cookbooks",
58
- "REQUEST_PATH" => "/organizations/local-test-org/cookbooks",
59
- "CONTENT_TYPE" => "multipart/form-data; boundary=----RubyMultipartClient6792ZZZZZ",
60
- "CONTENT_LENGTH" => "394",
61
- }
62
- @request = request.new(@merb_headers, "POST", "/nodes")
63
- @http_authentication_request = Mixlib::Authentication::HTTPAuthenticationRequest.new(@request)
64
- end
65
-
66
- it "normalizes the headers to lowercase symbols" do
67
- expected = { :host => "127.0.0.1",
68
- :x_ops_sign => "version=1.0",
69
- :x_ops_requestid => "127.0.0.1 1258566194.85386",
70
- :x_ops_timestamp => "2009-01-01T12:00:00Z",
71
- :x_ops_content_hash => "DFteJZPVv6WKdQmMqZUQUumUyRs=",
72
- :x_ops_userid => "spec-user",
73
- :x_ops_authorization_1 => "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4",
74
- :x_ops_authorization_2 => "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
75
- :x_ops_authorization_3 => "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
76
- :x_ops_authorization_4 => "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
77
- :x_ops_authorization_5 => "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0",
78
- :x_ops_authorization_6 => "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" }
79
- expect(@http_authentication_request.headers).to eq(expected)
80
- end
81
-
82
- it "raises an error when not all required headers are given" do
83
- @merb_headers.delete("HTTP_X_OPS_SIGN")
84
- exception = Mixlib::Authentication::MissingAuthenticationHeader
85
- expect { Mixlib::Authentication::HTTPAuthenticationRequest.new(@request) }.to raise_error(exception)
86
- end
87
-
88
- it "extracts the path from the request" do
89
- expect(@http_authentication_request.path).to eq("/nodes")
90
- end
91
-
92
- it "extracts the request method from the request" do
93
- expect(@http_authentication_request.http_method).to eq("POST")
94
- end
95
-
96
- it "extracts the signing description from the request headers" do
97
- expect(@http_authentication_request.signing_description).to eq("version=1.0")
98
- end
99
-
100
- it "extracts the user_id from the request headers" do
101
- expect(@http_authentication_request.user_id).to eq("spec-user")
102
- end
103
-
104
- it "extracts the timestamp from the request headers" do
105
- expect(@http_authentication_request.timestamp).to eq("2009-01-01T12:00:00Z")
106
- end
107
-
108
- it "extracts the host from the request headers" do
109
- expect(@http_authentication_request.host).to eq("127.0.0.1")
110
- end
111
-
112
- it "extracts the content hash from the request headers" do
113
- expect(@http_authentication_request.content_hash).to eq("DFteJZPVv6WKdQmMqZUQUumUyRs=")
114
- end
115
-
116
- it "rebuilds the request signature from the headers" do
117
- expected = <<-SIG
118
- jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4
119
- NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc
120
- 3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O
121
- IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy
122
- 9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0
123
- utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==
124
- SIG
125
- expect(@http_authentication_request.request_signature).to eq(expected.chomp)
126
- end
127
-
128
- it "defaults to server api version 0" do
129
- expect(@http_authentication_request.server_api_version).to eq("0")
130
- end
131
-
132
- end
@@ -1,596 +0,0 @@
1
- #
2
- # Author:: Tim Hinderliter (<tim@opscode.com>)
3
- # Author:: Christopher Walters (<cw@opscode.com>)
4
- # Author:: Christopher Brown (<cb@opscode.com>)
5
- # Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
6
- # License:: Apache License, Version 2.0
7
- #
8
- # Licensed under the Apache License, Version 2.0 (the "License");
9
- # you may not use this file except in compliance with the License.
10
- # You may obtain a copy of the License at
11
- #
12
- # http://www.apache.org/licenses/LICENSE-2.0
13
- #
14
- # Unless required by applicable law or agreed to in writing, software
15
- # distributed under the License is distributed on an "AS IS" BASIS,
16
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- # See the License for the specific language governing permissions and
18
- # limitations under the License.
19
- #
20
-
21
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
22
- require "rubygems"
23
-
24
- require "ostruct"
25
- require "openssl"
26
- require "mixlib/authentication/signatureverification"
27
- require "time"
28
-
29
- # TODO: should make these regular spec-based mock objects.
30
- class MockRequest
31
- attr_accessor :env, :params, :path, :raw_post
32
-
33
- def initialize(path, params, headers, raw_post)
34
- @path = path
35
- @params = params
36
- @env = headers
37
- @raw_post = raw_post
38
- end
39
-
40
- def method
41
- "POST"
42
- end
43
- end
44
-
45
- class MockFile
46
- def initialize
47
- @have_read = nil
48
- end
49
-
50
- def self.length
51
- BODY.length
52
- end
53
-
54
- def read(len, out_str)
55
- if @have_read.nil?
56
- @have_read = 1
57
- out_str[0..-1] = BODY
58
- BODY
59
- else
60
- nil
61
- end
62
- end
63
- end
64
-
65
- # Uncomment this to get some more info from the methods we're testing.
66
- #Mixlib::Authentication.logger.level = :trace
67
-
68
- describe "Mixlib::Authentication::SignedHeaderAuth" do
69
-
70
- # NOTE: Version 1.0 will be the default until Chef 11 is released.
71
-
72
- it "should generate the correct string to sign and signature, version 1.0 (default)" do
73
-
74
- expect(V1_0_SIGNING_OBJECT.canonicalize_request).to eq(V1_0_CANONICAL_REQUEST)
75
-
76
- # If you need to regenerate the constants in this test spec, print out
77
- # the results of res.inspect and copy them as appropriate into the
78
- # the constants in this file.
79
- expect(V1_0_SIGNING_OBJECT.sign(PRIVATE_KEY)).to eq(EXPECTED_SIGN_RESULT_V1_0)
80
- end
81
-
82
- it "should generate the correct string to sign and signature, version 1.1" do
83
- expect(V1_1_SIGNING_OBJECT.proto_version).to eq("1.1")
84
- expect(V1_1_SIGNING_OBJECT.canonicalize_request).to eq(V1_1_CANONICAL_REQUEST)
85
-
86
- # If you need to regenerate the constants in this test spec, print out
87
- # the results of res.inspect and copy them as appropriate into the
88
- # the constants in this file.
89
- expect(V1_1_SIGNING_OBJECT.sign(PRIVATE_KEY)).to eq(EXPECTED_SIGN_RESULT_V1_1)
90
- end
91
-
92
- it "should generate the correct string to sign and signature for version 1.3 with SHA256" do
93
- expect(V1_3_SHA256_SIGNING_OBJECT.proto_version).to eq("1.3")
94
- expect(V1_3_SHA256_SIGNING_OBJECT.algorithm).to eq("sha256")
95
- expect(V1_3_SHA256_SIGNING_OBJECT.server_api_version).to eq("1")
96
- expect(V1_3_SHA256_SIGNING_OBJECT.canonicalize_request).to eq(V1_3_SHA256_CANONICAL_REQUEST)
97
-
98
- # If you need to regenerate the constants in this test spec, print out
99
- # the results of res.inspect and copy them as appropriate into the
100
- # the constants in this file.
101
- expect(V1_3_SHA256_SIGNING_OBJECT.sign(PRIVATE_KEY)).to eq(EXPECTED_SIGN_RESULT_V1_3_SHA256)
102
- end
103
-
104
- it "should generate the correct string to sign and signature for non-default proto version when used as a mixin" do
105
- algorithm = "sha1"
106
- version = "1.1"
107
-
108
- V1_1_SIGNING_OBJECT.proto_version = "1.0"
109
- expect(V1_1_SIGNING_OBJECT.proto_version).to eq("1.0")
110
- expect(V1_1_SIGNING_OBJECT.canonicalize_request(algorithm, version)).to eq(V1_1_CANONICAL_REQUEST)
111
-
112
- # If you need to regenerate the constants in this test spec, print out
113
- # the results of res.inspect and copy them as appropriate into the
114
- # the constants in this file.
115
- expect(V1_1_SIGNING_OBJECT.sign(PRIVATE_KEY, algorithm, version)).to eq(EXPECTED_SIGN_RESULT_V1_1)
116
- end
117
-
118
- it "should not choke when signing a request for a long user id with version 1.1" do
119
- expect { LONG_SIGNING_OBJECT.sign(PRIVATE_KEY, "sha1", "1.1") }.not_to raise_error
120
- end
121
-
122
- it "should choke when signing a request for a long user id with version 1.0" do
123
- expect { LONG_SIGNING_OBJECT.sign(PRIVATE_KEY, "sha1", "1.0") }.to raise_error(OpenSSL::PKey::RSAError)
124
- end
125
-
126
- it "should choke when signing a request with a bad version" do
127
- expect { V1_1_SIGNING_OBJECT.sign(PRIVATE_KEY, "sha1", "poo") }.to raise_error(Mixlib::Authentication::AuthenticationError)
128
- end
129
-
130
- it "should choke when signing a request with a bad algorithm" do
131
- expect { V1_1_SIGNING_OBJECT.sign(PRIVATE_KEY, "sha_poo", "1.1") }.to raise_error(Mixlib::Authentication::AuthenticationError)
132
- end
133
-
134
- end
135
-
136
- describe "Mixlib::Authentication::SignatureVerification" do
137
-
138
- before(:each) do
139
- @user_private_key = PRIVATE_KEY
140
- end
141
-
142
- it "should authenticate a File-containing request V1.1 - Merb" do
143
- request_params = MERB_REQUEST_PARAMS.clone
144
- request_params["file"] =
145
- { "size" => MockFile.length, "content_type" => "application/octet-stream", "filename" => "zsh.tar.gz", "tempfile" => MockFile.new }
146
-
147
- mock_request = MockRequest.new(PATH, request_params, MERB_HEADERS_V1_1, "")
148
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
149
-
150
- service = Mixlib::Authentication::SignatureVerification.new
151
- res = service.authenticate_user_request(mock_request, @user_private_key)
152
- expect(res).not_to be_nil
153
- end
154
-
155
- it "should authenticate a File-containing request V1.3 SHA256 - Merb" do
156
- request_params = MERB_REQUEST_PARAMS.clone
157
- request_params["file"] =
158
- { "size" => MockFile.length, "content_type" => "application/octet-stream", "filename" => "zsh.tar.gz", "tempfile" => MockFile.new }
159
-
160
- mock_request = MockRequest.new(PATH, request_params, MERB_HEADERS_V1_3_SHA256, "")
161
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
162
-
163
- service = Mixlib::Authentication::SignatureVerification.new
164
- res = service.authenticate_user_request(mock_request, @user_private_key)
165
- expect(res).not_to be_nil
166
- end
167
-
168
- it "should authenticate a File-containing request from a v1.0 client - Passenger" do
169
- request_params = PASSENGER_REQUEST_PARAMS.clone
170
- request_params["tarball"] = MockFile.new
171
-
172
- mock_request = MockRequest.new(PATH, request_params, PASSENGER_HEADERS_V1_0, "")
173
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
174
-
175
- auth_req = Mixlib::Authentication::SignatureVerification.new
176
- res = auth_req.authenticate_user_request(mock_request, @user_private_key)
177
- expect(res).not_to be_nil
178
- end
179
-
180
- it "should authenticate a normal (post body) request v1.3 SHA256 - Merb" do
181
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_3_SHA256, BODY)
182
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
183
-
184
- service = Mixlib::Authentication::SignatureVerification.new
185
- res = service.authenticate_user_request(mock_request, @user_private_key)
186
- expect(res).not_to be_nil
187
- end
188
-
189
- it "should authenticate a normal (post body) request v1.1 - Merb" do
190
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_1, BODY)
191
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
192
-
193
- service = Mixlib::Authentication::SignatureVerification.new
194
- res = service.authenticate_user_request(mock_request, @user_private_key)
195
- expect(res).not_to be_nil
196
- end
197
-
198
- it "should authenticate a normal (post body) request from a v1.0 client - Merb" do
199
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_0, BODY)
200
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
201
-
202
- service = Mixlib::Authentication::SignatureVerification.new
203
- res = service.authenticate_user_request(mock_request, @user_private_key)
204
- expect(res).not_to be_nil
205
- end
206
-
207
- it "shouldn't authenticate if an Authorization header is missing" do
208
- headers = MERB_HEADERS_V1_1.clone
209
- headers.delete("HTTP_X_OPS_SIGN")
210
-
211
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, headers, BODY)
212
- allow(Time).to receive(:now).and_return(TIMESTAMP_OBJ)
213
- #Time.stub!(:now).and_return(TIMESTAMP_OBJ)
214
-
215
- auth_req = Mixlib::Authentication::SignatureVerification.new
216
- expect { auth_req.authenticate_user_request(mock_request, @user_private_key) }.to raise_error(Mixlib::Authentication::AuthenticationError)
217
-
218
- expect(auth_req).not_to be_a_valid_request
219
- expect(auth_req).not_to be_a_valid_timestamp
220
- expect(auth_req).not_to be_a_valid_signature
221
- expect(auth_req).not_to be_a_valid_content_hash
222
- end
223
-
224
- it "shouldn't authenticate if Authorization header is wrong" do
225
- headers = MERB_HEADERS_V1_1.clone
226
- headers["HTTP_X_OPS_CONTENT_HASH"] += "_"
227
-
228
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, headers, BODY)
229
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
230
-
231
- auth_req = Mixlib::Authentication::SignatureVerification.new
232
- res = auth_req.authenticate_user_request(mock_request, @user_private_key)
233
- expect(res).to be_nil
234
-
235
- expect(auth_req).not_to be_a_valid_request
236
- expect(auth_req).to be_a_valid_timestamp
237
- expect(auth_req).to be_a_valid_signature
238
- expect(auth_req).not_to be_a_valid_content_hash
239
- end
240
-
241
- it "shouldn't authenticate if the timestamp is not within bounds" do
242
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_1, BODY)
243
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ - 1000)
244
-
245
- auth_req = Mixlib::Authentication::SignatureVerification.new
246
- res = auth_req.authenticate_user_request(mock_request, @user_private_key)
247
- expect(res).to be_nil
248
- expect(auth_req).not_to be_a_valid_request
249
- expect(auth_req).not_to be_a_valid_timestamp
250
- expect(auth_req).to be_a_valid_signature
251
- expect(auth_req).to be_a_valid_content_hash
252
- end
253
-
254
- it "shouldn't authenticate if the signature is wrong" do
255
- headers = MERB_HEADERS_V1_1.dup
256
- headers["HTTP_X_OPS_AUTHORIZATION_1"] = "epicfail"
257
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, headers, BODY)
258
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
259
-
260
- auth_req = Mixlib::Authentication::SignatureVerification.new
261
- res = auth_req.authenticate_user_request(mock_request, @user_private_key)
262
- expect(res).to be_nil
263
- expect(auth_req).not_to be_a_valid_request
264
- expect(auth_req).not_to be_a_valid_signature
265
- expect(auth_req).to be_a_valid_timestamp
266
- expect(auth_req).to be_a_valid_content_hash
267
- end
268
-
269
- it "shouldn't authenticate if the signature is wrong for v1.3 SHA256" do
270
- headers = MERB_HEADERS_V1_3_SHA256.dup
271
- headers["HTTP_X_OPS_AUTHORIZATION_1"] = "epicfail"
272
- mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, headers, BODY)
273
- expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ)
274
-
275
- auth_req = Mixlib::Authentication::SignatureVerification.new
276
- res = auth_req.authenticate_user_request(mock_request, @user_private_key)
277
- expect(res).to be_nil
278
- expect(auth_req).not_to be_a_valid_request
279
- expect(auth_req).not_to be_a_valid_signature
280
- expect(auth_req).to be_a_valid_timestamp
281
- expect(auth_req).to be_a_valid_content_hash
282
- end
283
- end
284
-
285
- USER_ID = "spec-user"
286
- DIGESTED_USER_ID = Base64.encode64(Digest::SHA1.new.digest(USER_ID)).chomp
287
- BODY = "Spec Body"
288
- HASHED_BODY = "DFteJZPVv6WKdQmMqZUQUumUyRs=" # Base64.encode64(Digest::SHA1.digest("Spec Body")).chomp
289
- HASHED_BODY_SHA256 = "hDlKNZhIhgso3Fs0S0pZwJ0xyBWtR1RBaeHs1DrzOho="
290
- TIMESTAMP_ISO8601 = "2009-01-01T12:00:00Z"
291
- TIMESTAMP_OBJ = Time.parse("Thu Jan 01 12:00:00 -0000 2009")
292
- PATH = "/organizations/clownco"
293
- HASHED_CANONICAL_PATH = "YtBWDn1blGGuFIuKksdwXzHU9oE=" # Base64.encode64(Digest::SHA1.digest("/organizations/clownco")).chomp
294
-
295
- V1_0_ARGS = {
296
- :body => BODY,
297
- :user_id => USER_ID,
298
- :http_method => :post,
299
- :timestamp => TIMESTAMP_ISO8601, # fixed timestamp so we get back the same answer each time.
300
- :file => MockFile.new,
301
- :path => PATH,
302
- }
303
-
304
- V1_1_ARGS = {
305
- :body => BODY,
306
- :user_id => USER_ID,
307
- :http_method => :post,
308
- :timestamp => TIMESTAMP_ISO8601, # fixed timestamp so we get back the same answer each time.
309
- :file => MockFile.new,
310
- :path => PATH,
311
- :proto_version => 1.1,
312
- }
313
-
314
- V1_3_ARGS_SHA256 = {
315
- :body => BODY,
316
- :user_id => USER_ID,
317
- :http_method => :post,
318
- :timestamp => TIMESTAMP_ISO8601, # fixed timestamp so we get back the same answer each time.
319
- :file => MockFile.new,
320
- :path => PATH,
321
- :proto_version => "1.3",
322
- :headers => {
323
- "X-OpS-SeRvEr-ApI-VerSiOn" => "1",
324
- }
325
- # This defaults to sha256
326
- }
327
-
328
- LONG_PATH_LONG_USER_ARGS = {
329
- :body => BODY,
330
- :user_id => "A" * 200,
331
- :http_method => :put,
332
- :timestamp => TIMESTAMP_ISO8601, # fixed timestamp so we get back the same answer each time.
333
- :file => MockFile.new,
334
- :path => PATH + "/nodes/#{"A" * 250}",
335
- }
336
-
337
- REQUESTING_ACTOR_ID = "c0f8a68c52bffa1020222a56b23cccfa"
338
-
339
- # Content hash is ???TODO
340
- X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs="
341
- X_OPS_CONTENT_HASH_SHA256 = "hDlKNZhIhgso3Fs0S0pZwJ0xyBWtR1RBaeHs1DrzOho="
342
-
343
- X_OPS_AUTHORIZATION_LINES_V1_0 = [
344
- "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4",
345
- "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
346
- "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
347
- "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
348
- "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0",
349
- "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==",
350
- ]
351
-
352
- X_OPS_AUTHORIZATION_LINES = [
353
- "UfZD9dRz6rFu6LbP5Mo1oNHcWYxpNIcUfFCffJS1FQa0GtfU/vkt3/O5HuCM",
354
- "1wIFl/U0f5faH9EWpXWY5NwKR031Myxcabw4t4ZLO69CIh/3qx1XnjcZvt2w",
355
- "c2R9bx/43IWA/r8w8Q6decuu0f6ZlNheJeJhaYPI8piX/aH+uHBH8zTACZu8",
356
- "vMnl5MF3/OIlsZc8cemq6eKYstp8a8KYq9OmkB5IXIX6qVMJHA6fRvQEB/7j",
357
- "281Q7oI/O+lE8AmVyBbwruPb7Mp6s4839eYiOdjbDwFjYtbS3XgAjrHlaD7W",
358
- "FDlbAG7H8Dmvo+wBxmtNkszhzbBnEYtuwQqT8nM/8A==",
359
- ]
360
-
361
- X_OPS_AUTHORIZATION_LINES_V1_3_SHA256 = [
362
- "FZOmXAyOBAZQV/uw188iBljBJXOm+m8xQ/8KTGLkgGwZNcRFxk1m953XjE3W",
363
- "VGy1dFT76KeaNWmPCNtDmprfH2na5UZFtfLIKrPv7xm80V+lzEzTd9WBwsfP",
364
- "42dZ9N+V9I5SVfcL/lWrrlpdybfceJC5jOcP5tzfJXWUITwb6Z3Erg3DU3Uh",
365
- "H9h9E0qWlYGqmiNCVrBnpe6Si1gU/Jl+rXlRSNbLJ4GlArAPuL976iTYJTzE",
366
- "MmbLUIm3JRYi00Yb01IUCCKdI90vUq1HHNtlTEu93YZfQaJwRxXlGkCNwIJe",
367
- "fy49QzaCIEu1XiOx5Jn+4GmkrZch/RrK9VzQWXgs+w==",
368
- ]
369
- # We expect Mixlib::Authentication::SignedHeaderAuth#sign to return this
370
- # if passed the BODY above, based on version
371
-
372
- EXPECTED_SIGN_RESULT_V1_0 = {
373
- "X-Ops-Content-Hash" => X_OPS_CONTENT_HASH,
374
- "X-Ops-Userid" => USER_ID,
375
- "X-Ops-Sign" => "algorithm=sha1;version=1.0;",
376
- "X-Ops-Authorization-1" => X_OPS_AUTHORIZATION_LINES_V1_0[0],
377
- "X-Ops-Authorization-2" => X_OPS_AUTHORIZATION_LINES_V1_0[1],
378
- "X-Ops-Authorization-3" => X_OPS_AUTHORIZATION_LINES_V1_0[2],
379
- "X-Ops-Authorization-4" => X_OPS_AUTHORIZATION_LINES_V1_0[3],
380
- "X-Ops-Authorization-5" => X_OPS_AUTHORIZATION_LINES_V1_0[4],
381
- "X-Ops-Authorization-6" => X_OPS_AUTHORIZATION_LINES_V1_0[5],
382
- "X-Ops-Timestamp" => TIMESTAMP_ISO8601,
383
- }
384
-
385
- EXPECTED_SIGN_RESULT_V1_1 = {
386
- "X-Ops-Content-Hash" => X_OPS_CONTENT_HASH,
387
- "X-Ops-Userid" => USER_ID,
388
- "X-Ops-Sign" => "algorithm=sha1;version=1.1;",
389
- "X-Ops-Authorization-1" => X_OPS_AUTHORIZATION_LINES[0],
390
- "X-Ops-Authorization-2" => X_OPS_AUTHORIZATION_LINES[1],
391
- "X-Ops-Authorization-3" => X_OPS_AUTHORIZATION_LINES[2],
392
- "X-Ops-Authorization-4" => X_OPS_AUTHORIZATION_LINES[3],
393
- "X-Ops-Authorization-5" => X_OPS_AUTHORIZATION_LINES[4],
394
- "X-Ops-Authorization-6" => X_OPS_AUTHORIZATION_LINES[5],
395
- "X-Ops-Timestamp" => TIMESTAMP_ISO8601,
396
- }
397
-
398
- EXPECTED_SIGN_RESULT_V1_3_SHA256 = {
399
- "X-Ops-Content-Hash" => X_OPS_CONTENT_HASH_SHA256,
400
- "X-Ops-Userid" => USER_ID,
401
- "X-Ops-Sign" => "algorithm=sha256;version=1.3;",
402
- "X-Ops-Authorization-1" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[0],
403
- "X-Ops-Authorization-2" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[1],
404
- "X-Ops-Authorization-3" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[2],
405
- "X-Ops-Authorization-4" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[3],
406
- "X-Ops-Authorization-5" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[4],
407
- "X-Ops-Authorization-6" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[5],
408
- "X-Ops-Timestamp" => TIMESTAMP_ISO8601,
409
- }
410
-
411
- OTHER_HEADERS = {
412
- # An arbitrary sampling of non-HTTP_* headers are in here to
413
- # exercise that code path.
414
- "REMOTE_ADDR" => "127.0.0.1",
415
- "PATH_INFO" => "/organizations/local-test-org/cookbooks",
416
- "REQUEST_PATH" => "/organizations/local-test-org/cookbooks",
417
- "CONTENT_TYPE" => "multipart/form-data; boundary=----RubyMultipartClient6792ZZZZZ",
418
- "CONTENT_LENGTH" => "394",
419
- }
420
-
421
- # This is what will be in request.params for the Merb case.
422
- MERB_REQUEST_PARAMS = {
423
- "name" => "zsh", "action" => "create", "controller" => "chef_server_api/cookbooks",
424
- "organization_id" => "local-test-org", "requesting_actor_id" => REQUESTING_ACTOR_ID
425
- }
426
-
427
- MERB_HEADERS_V1_3_SHA256 = {
428
- # These are used by signatureverification.
429
- "HTTP_HOST" => "127.0.0.1",
430
- "HTTP_X_OPS_SIGN" => "algorithm=sha256;version=1.3;",
431
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
432
- "HTTP_X_OPS_TIMESTAMP" => TIMESTAMP_ISO8601,
433
- "HTTP_X_OPS_CONTENT_HASH" => X_OPS_CONTENT_HASH_SHA256,
434
- "HTTP_X_OPS_USERID" => USER_ID,
435
- "HTTP_X_OPS_SERVER_API_VERSION" => "1",
436
- "HTTP_X_OPS_AUTHORIZATION_1" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[0],
437
- "HTTP_X_OPS_AUTHORIZATION_2" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[1],
438
- "HTTP_X_OPS_AUTHORIZATION_3" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[2],
439
- "HTTP_X_OPS_AUTHORIZATION_4" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[3],
440
- "HTTP_X_OPS_AUTHORIZATION_5" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[4],
441
- "HTTP_X_OPS_AUTHORIZATION_6" => X_OPS_AUTHORIZATION_LINES_V1_3_SHA256[5],
442
- }.merge(OTHER_HEADERS)
443
-
444
- # Tis is what will be in request.env for the Merb case.
445
- MERB_HEADERS_V1_1 = {
446
- # These are used by signatureverification.
447
- "HTTP_HOST" => "127.0.0.1",
448
- "HTTP_X_OPS_SIGN" => "algorithm=sha1;version=1.1;",
449
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
450
- "HTTP_X_OPS_TIMESTAMP" => TIMESTAMP_ISO8601,
451
- "HTTP_X_OPS_CONTENT_HASH" => X_OPS_CONTENT_HASH,
452
- "HTTP_X_OPS_USERID" => USER_ID,
453
- "HTTP_X_OPS_AUTHORIZATION_1" => X_OPS_AUTHORIZATION_LINES[0],
454
- "HTTP_X_OPS_AUTHORIZATION_2" => X_OPS_AUTHORIZATION_LINES[1],
455
- "HTTP_X_OPS_AUTHORIZATION_3" => X_OPS_AUTHORIZATION_LINES[2],
456
- "HTTP_X_OPS_AUTHORIZATION_4" => X_OPS_AUTHORIZATION_LINES[3],
457
- "HTTP_X_OPS_AUTHORIZATION_5" => X_OPS_AUTHORIZATION_LINES[4],
458
- "HTTP_X_OPS_AUTHORIZATION_6" => X_OPS_AUTHORIZATION_LINES[5],
459
- }.merge(OTHER_HEADERS)
460
-
461
- # Tis is what will be in request.env for the Merb case.
462
- MERB_HEADERS_V1_0 = {
463
- # These are used by signatureverification.
464
- "HTTP_HOST" => "127.0.0.1",
465
- "HTTP_X_OPS_SIGN" => "version=1.0",
466
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
467
- "HTTP_X_OPS_TIMESTAMP" => TIMESTAMP_ISO8601,
468
- "HTTP_X_OPS_CONTENT_HASH" => X_OPS_CONTENT_HASH,
469
- "HTTP_X_OPS_USERID" => USER_ID,
470
- "HTTP_X_OPS_AUTHORIZATION_1" => X_OPS_AUTHORIZATION_LINES_V1_0[0],
471
- "HTTP_X_OPS_AUTHORIZATION_2" => X_OPS_AUTHORIZATION_LINES_V1_0[1],
472
- "HTTP_X_OPS_AUTHORIZATION_3" => X_OPS_AUTHORIZATION_LINES_V1_0[2],
473
- "HTTP_X_OPS_AUTHORIZATION_4" => X_OPS_AUTHORIZATION_LINES_V1_0[3],
474
- "HTTP_X_OPS_AUTHORIZATION_5" => X_OPS_AUTHORIZATION_LINES_V1_0[4],
475
- "HTTP_X_OPS_AUTHORIZATION_6" => X_OPS_AUTHORIZATION_LINES_V1_0[5],
476
- }.merge(OTHER_HEADERS)
477
-
478
- PASSENGER_REQUEST_PARAMS = {
479
- "action" => "create",
480
- #"tarball"=>#<File:/tmp/RackMultipart20091120-25570-mgq2sa-0>,
481
- "controller" => "api/v1/cookbooks",
482
- "cookbook" => "{\"category\":\"databases\"}",
483
- }
484
-
485
- PASSENGER_HEADERS_V1_1 = {
486
- # These are used by signatureverification.
487
- "HTTP_HOST" => "127.0.0.1",
488
- "HTTP_X_OPS_SIGN" => "algorithm=sha1;version=1.1;",
489
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
490
- "HTTP_X_OPS_TIMESTAMP" => TIMESTAMP_ISO8601,
491
- "HTTP_X_OPS_CONTENT_HASH" => X_OPS_CONTENT_HASH,
492
- "HTTP_X_OPS_USERID" => USER_ID,
493
- "HTTP_X_OPS_AUTHORIZATION_1" => X_OPS_AUTHORIZATION_LINES[0],
494
- "HTTP_X_OPS_AUTHORIZATION_2" => X_OPS_AUTHORIZATION_LINES[1],
495
- "HTTP_X_OPS_AUTHORIZATION_3" => X_OPS_AUTHORIZATION_LINES[2],
496
- "HTTP_X_OPS_AUTHORIZATION_4" => X_OPS_AUTHORIZATION_LINES[3],
497
- "HTTP_X_OPS_AUTHORIZATION_5" => X_OPS_AUTHORIZATION_LINES[4],
498
- "HTTP_X_OPS_AUTHORIZATION_6" => X_OPS_AUTHORIZATION_LINES[5],
499
- }.merge(OTHER_HEADERS)
500
-
501
- PASSENGER_HEADERS_V1_0 = {
502
- # These are used by signatureverification.
503
- "HTTP_HOST" => "127.0.0.1",
504
- "HTTP_X_OPS_SIGN" => "version=1.0",
505
- "HTTP_X_OPS_REQUESTID" => "127.0.0.1 1258566194.85386",
506
- "HTTP_X_OPS_TIMESTAMP" => TIMESTAMP_ISO8601,
507
- "HTTP_X_OPS_CONTENT_HASH" => X_OPS_CONTENT_HASH,
508
- "HTTP_X_OPS_USERID" => USER_ID,
509
- "HTTP_X_OPS_AUTHORIZATION_1" => X_OPS_AUTHORIZATION_LINES_V1_0[0],
510
- "HTTP_X_OPS_AUTHORIZATION_2" => X_OPS_AUTHORIZATION_LINES_V1_0[1],
511
- "HTTP_X_OPS_AUTHORIZATION_3" => X_OPS_AUTHORIZATION_LINES_V1_0[2],
512
- "HTTP_X_OPS_AUTHORIZATION_4" => X_OPS_AUTHORIZATION_LINES_V1_0[3],
513
- "HTTP_X_OPS_AUTHORIZATION_5" => X_OPS_AUTHORIZATION_LINES_V1_0[4],
514
- "HTTP_X_OPS_AUTHORIZATION_6" => X_OPS_AUTHORIZATION_LINES_V1_0[5],
515
- }.merge(OTHER_HEADERS)
516
-
517
- # generated with
518
- # openssl genrsa -out private.pem 2048
519
- # openssl rsa -in private.pem -out public.pem -pubout
520
- PUBLIC_KEY_DATA = <<EOS
521
- -----BEGIN PUBLIC KEY-----
522
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ueqo76MXuP6XqZBILFz
523
- iH/9AI7C6PaN5W0dSvkr9yInyGHSz/IR1+4tqvP2qlfKVKI4CP6BFH251Ft9qMUB
524
- uAsnlAVQ1z0exDtIFFOyQCdR7iXmjBIWMSS4buBwRQXwDK7id1OxtU23qVJv+xwE
525
- V0IzaaSJmaGLIbvRBD+qatfUuQJBMU/04DdJIwvLtZBYdC2219m5dUBQaa4bimL+
526
- YN9EcsDzD9h9UxQo5ReK7b3cNMzJBKJWLzFBcJuePMzAnLFktr/RufX4wpXe6XJx
527
- oVPaHo72GorLkwnQ0HYMTY8rehT4mDi1FI969LHCFFaFHSAaRnwdXaQkJmSfcxzC
528
- YQIDAQAB
529
- -----END PUBLIC KEY-----
530
- EOS
531
-
532
- PRIVATE_KEY_DATA = <<EOS
533
- -----BEGIN RSA PRIVATE KEY-----
534
- MIIEpAIBAAKCAQEA0ueqo76MXuP6XqZBILFziH/9AI7C6PaN5W0dSvkr9yInyGHS
535
- z/IR1+4tqvP2qlfKVKI4CP6BFH251Ft9qMUBuAsnlAVQ1z0exDtIFFOyQCdR7iXm
536
- jBIWMSS4buBwRQXwDK7id1OxtU23qVJv+xwEV0IzaaSJmaGLIbvRBD+qatfUuQJB
537
- MU/04DdJIwvLtZBYdC2219m5dUBQaa4bimL+YN9EcsDzD9h9UxQo5ReK7b3cNMzJ
538
- BKJWLzFBcJuePMzAnLFktr/RufX4wpXe6XJxoVPaHo72GorLkwnQ0HYMTY8rehT4
539
- mDi1FI969LHCFFaFHSAaRnwdXaQkJmSfcxzCYQIDAQABAoIBAQCW3I4sKN5B9jOe
540
- xq/pkeWBq4OvhW8Ys1yW0zFT8t6nHbB1XrwscQygd8gE9BPqj3e0iIEqtdphbPmj
541
- VHqTYbC0FI6QDClifV7noTwTBjeIOlgZ0NSUN0/WgVzIOxUz2mZ2vBZUovKILPqG
542
- TOi7J7RXMoySMdcXpP1f+PgvYNcnKsT72UcWaSXEV8/zo+Zm/qdGPVWwJonri5Mp
543
- DVm5EQSENBiRyt028rU6ElXORNmoQpVjDVqZ1gipzXkifdjGyENw2rt4V/iKYD7V
544
- 5iqXOsvP6Cemf4gbrjunAgDG08S00kiUgvVWcdXW+dlsR2nCvH4DOEe3AYYh/aH8
545
- DxEE7FbtAoGBAPcNO8fJ56mNw0ow4Qg38C+Zss/afhBOCfX4O/SZKv/roRn5+gRM
546
- KRJYSVXNnsjPI1plzqR4OCyOrjAhtuvL4a0DinDzf1+fiztyNohwYsW1vYmqn3ti
547
- EN0GhSgE7ppZjqvLQ3f3LUTxynhA0U+k9wflb4irIlViTUlCsOPkrNJDAoGBANqL
548
- Q+vvuGSsmRLU/Cenjy+Mjj6+QENg51dz34o8JKuVKIPKU8pNnyeLa5fat0qD2MHm
549
- OB9opeQOcw0dStodxr6DB3wi83bpjeU6BWUGITNiWEaZEBrQ0aiqNJJKrrHm8fAZ
550
- 9o4l4oHc4hI0kYVYYDuxtKuVJrzZiEapTwoOcYiLAoGBAI/EWbeIHZIj9zOjgjEA
551
- LHvm25HtulLOtyk2jd1njQhlHNk7CW2azIPqcLLH99EwCYi/miNH+pijZ2aHGCXb
552
- /bZrSxM0ADmrZKDxdB6uGCyp+GS2sBxjEyEsfCyvwhJ8b3Q100tqwiNO+d5FCglp
553
- HICx2dgUjuRVUliBwOK93nx1AoGAUI8RhIEjOYkeDAESyhNMBr0LGjnLOosX+/as
554
- qiotYkpjWuFULbibOFp+WMW41vDvD9qrSXir3fstkeIAW5KqVkO6mJnRoT3Knnra
555
- zjiKOITCAZQeiaP8BO5o3pxE9TMqb9VCO3ffnPstIoTaN4syPg7tiGo8k1SklVeH
556
- 2S8lzq0CgYAKG2fljIYWQvGH628rp4ZcXS4hWmYohOxsnl1YrszbJ+hzR+IQOhGl
557
- YlkUQYXhy9JixmUUKtH+NXkKX7Lyc8XYw5ETr7JBT3ifs+G7HruDjVG78EJVojbd
558
- 8uLA+DdQm5mg4vd1GTiSK65q/3EeoBlUaVor3HhLFki+i9qpT8CBsg==
559
- -----END RSA PRIVATE KEY-----
560
- EOS
561
-
562
- PRIVATE_KEY = OpenSSL::PKey::RSA.new(PRIVATE_KEY_DATA)
563
-
564
- V1_0_CANONICAL_REQUEST_DATA = <<EOS
565
- Method:POST
566
- Hashed Path:#{HASHED_CANONICAL_PATH}
567
- X-Ops-Content-Hash:#{HASHED_BODY}
568
- X-Ops-Timestamp:#{TIMESTAMP_ISO8601}
569
- X-Ops-UserId:#{USER_ID}
570
- EOS
571
- V1_0_CANONICAL_REQUEST = V1_0_CANONICAL_REQUEST_DATA.chomp
572
-
573
- V1_1_CANONICAL_REQUEST_DATA = <<EOS
574
- Method:POST
575
- Hashed Path:#{HASHED_CANONICAL_PATH}
576
- X-Ops-Content-Hash:#{HASHED_BODY}
577
- X-Ops-Timestamp:#{TIMESTAMP_ISO8601}
578
- X-Ops-UserId:#{DIGESTED_USER_ID}
579
- EOS
580
- V1_1_CANONICAL_REQUEST = V1_1_CANONICAL_REQUEST_DATA.chomp
581
-
582
- V1_3_SHA256_CANONICAL_REQUEST_DATA = <<EOS
583
- Method:POST
584
- Path:#{PATH}
585
- X-Ops-Content-Hash:#{HASHED_BODY_SHA256}
586
- X-Ops-Sign:version=1.3
587
- X-Ops-Timestamp:#{TIMESTAMP_ISO8601}
588
- X-Ops-UserId:#{USER_ID}
589
- X-Ops-Server-API-Version:1
590
- EOS
591
- V1_3_SHA256_CANONICAL_REQUEST = V1_3_SHA256_CANONICAL_REQUEST_DATA.chomp
592
-
593
- V1_3_SHA256_SIGNING_OBJECT = Mixlib::Authentication::SignedHeaderAuth.signing_object(V1_3_ARGS_SHA256)
594
- V1_1_SIGNING_OBJECT = Mixlib::Authentication::SignedHeaderAuth.signing_object(V1_1_ARGS)
595
- V1_0_SIGNING_OBJECT = Mixlib::Authentication::SignedHeaderAuth.signing_object(V1_0_ARGS)
596
- LONG_SIGNING_OBJECT = Mixlib::Authentication::SignedHeaderAuth.signing_object(LONG_PATH_LONG_USER_ARGS)