mixlib-authentication 1.4.2 → 3.0.4

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.
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"
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 = :debug
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)