mixlib-authentication 2.0.0 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mixlib/authentication.rb +4 -4
- data/lib/mixlib/authentication/digester.rb +3 -3
- data/lib/mixlib/authentication/http_authentication_request.rb +4 -4
- data/lib/mixlib/authentication/signatureverification.rb +7 -7
- data/lib/mixlib/authentication/signedheaderauth.rb +115 -39
- data/lib/mixlib/authentication/version.rb +3 -2
- metadata +6 -87
- data/Gemfile +0 -7
- data/NOTICE +0 -7
- data/README.md +0 -23
- data/Rakefile +0 -18
- data/mixlib-authentication.gemspec +0 -22
- data/spec/mixlib/authentication/digester_spec.rb +0 -24
- data/spec/mixlib/authentication/http_authentication_request_spec.rb +0 -132
- data/spec/mixlib/authentication/mixlib_authentication_spec.rb +0 -596
- data/spec/mixlib/authentication/mixlib_log_missing_spec.rb +0 -55
- data/spec/spec_helper.rb +0 -22
data/Gemfile
DELETED
data/NOTICE
DELETED
data/README.md
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# Mixlib::Authentication
|
2
|
-
[](https://travis-ci.org/chef/mixlib-authentication) [](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)
|