From 366fcfb07938576128c9bffb0d5ea2056e9e0cbe Mon Sep 17 00:00:00 2001 From: Jay Mundrawala Date: Sat, 5 Dec 2015 14:23:34 -0800 Subject: Our signing versions only support 1 hashing algorithm each This removes SHA1 from v1.3. v1.0 and v1.1 support SHA1 only --- lib/mixlib/authentication/signedheaderauth.rb | 34 ++---- .../authentication/mixlib_authentication_spec.rb | 122 +-------------------- 2 files changed, 11 insertions(+), 145 deletions(-) diff --git a/lib/mixlib/authentication/signedheaderauth.rb b/lib/mixlib/authentication/signedheaderauth.rb index 8faf313..e0a5a7f 100644 --- a/lib/mixlib/authentication/signedheaderauth.rb +++ b/lib/mixlib/authentication/signedheaderauth.rb @@ -30,14 +30,14 @@ module Mixlib NULL_ARG = Object.new - ALGORITHMS_FOR_VERSION = { - '1.0' => ['sha1'], - '1.1' => ['sha1'], - '1.3' => ['sha256', 'sha1'], + ALGORITHM_FOR_VERSION = { + '1.0' => 'sha1', + '1.1' => 'sha1', + '1.3' => 'sha256', }.freeze() # Use of SUPPORTED_ALGORITHMS and SUPPORTED_VERSIONS is deprecated. Use - # ALGORITHMS_FOR_VERSION instead + # ALGORITHM_FOR_VERSION instead SUPPORTED_ALGORITHMS = ['sha1'].freeze SUPPORTED_VERSIONS = ['1.0', '1.1'].freeze @@ -81,13 +81,12 @@ module Mixlib args[:user_id], args[:file], args[:proto_version], - args[:signing_algorithm], args[:headers] ) end def algorithm - DEFAULT_SIGN_ALGORITHM + ALGORITHM_FOR_VERSION[proto_version] || DEFAULT_SIGN_ALGORITHM end def proto_version @@ -122,14 +121,14 @@ module Mixlib end def validate_sign_version_digest!(sign_algorithm, sign_version) - if ALGORITHMS_FOR_VERSION[sign_version].nil? + if ALGORITHM_FOR_VERSION[sign_version].nil? raise AuthenticationError, "Unsupported version '#{sign_version}'" end - if !ALGORITHMS_FOR_VERSION[sign_version].include?(sign_algorithm) + if ALGORITHM_FOR_VERSION[sign_version] != sign_algorithm raise AuthenticationError, - "Unsupported version '#{sign_version}'" + "Unsupported algorithm #{sign_algorithm} for version '#{sign_version}'" end case sign_algorithm @@ -264,26 +263,13 @@ module Mixlib # provides a more convenient interface to the constructor. class SigningObject < Struct.new(:http_method, :path, :body, :host, :timestamp, :user_id, :file, :proto_version, - :signing_algorithm, :headers) + :headers) include SignedHeaderAuth def proto_version (self[:proto_version] or DEFAULT_PROTO_VERSION).to_s end - def algorithm - if self[:signing_algorithm] - self[:signing_algorithm] - else - case proto_version - when '1.3' - ALGORITHMS_FOR_VERSION[proto_version].first - else - DEFAULT_SIGN_ALGORITHM - end - end - end - def server_api_version key = (self[:headers] || {}).keys.select do |k| k.downcase == 'x-ops-server-api-version' diff --git a/spec/mixlib/authentication/mixlib_authentication_spec.rb b/spec/mixlib/authentication/mixlib_authentication_spec.rb index 41cd7e9..143af47 100644 --- a/spec/mixlib/authentication/mixlib_authentication_spec.rb +++ b/spec/mixlib/authentication/mixlib_authentication_spec.rb @@ -90,22 +90,6 @@ describe "Mixlib::Authentication::SignedHeaderAuth" do expect(V1_1_SIGNING_OBJECT.sign(PRIVATE_KEY)).to eq(EXPECTED_SIGN_RESULT_V1_1) end - it "should generate the correct string to sign and signature for version 1.3 with SHA1" do - expect(V1_3_SHA1_SIGNING_OBJECT.proto_version).to eq("1.3") - expect(V1_3_SHA1_SIGNING_OBJECT.canonicalize_request).to eq(V1_3_SHA1_CANONICAL_REQUEST) - expect(V1_3_SHA1_SIGNING_OBJECT.algorithm).to eq("sha1") - expect(V1_3_SHA1_SIGNING_OBJECT.server_api_version).to eq("1") - - # If you need to regenerate the constants in this test spec, print out - # the results of res.inspect and copy them as appropriate into the - # the constants in this file. - expect(V1_3_SHA1_SIGNING_OBJECT.sign(PRIVATE_KEY)).to eq(EXPECTED_SIGN_RESULT_V1_3_SHA1) - end - - it "should default to server api version 0 for version 1.3" do - expect(V1_3_SHA1_SIGNING_OBJECT_API0.server_api_version).to eq('0') - end - it "should generate the correct string to sign and signature for version 1.3 with SHA256" do expect(V1_3_SHA256_SIGNING_OBJECT.proto_version).to eq("1.3") expect(V1_3_SHA256_SIGNING_OBJECT.algorithm).to eq("sha256") @@ -170,19 +154,6 @@ describe "Mixlib::Authentication::SignatureVerification" do expect(res).not_to be_nil end - it "should authenticate a File-containing request V1.3 SHA1 - Merb" do - request_params = MERB_REQUEST_PARAMS.clone - request_params["file"] = - { "size"=>MockFile.length, "content_type"=>"application/octet-stream", "filename"=>"zsh.tar.gz", "tempfile"=>MockFile.new } - - mock_request = MockRequest.new(PATH, request_params, MERB_HEADERS_V1_3_SHA1, "") - expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ) - - service = Mixlib::Authentication::SignatureVerification.new - res = service.authenticate_user_request(mock_request, @user_private_key) - expect(res).not_to be_nil - end - it "should authenticate a File-containing request V1.3 SHA256 - Merb" do request_params = MERB_REQUEST_PARAMS.clone request_params["file"] = @@ -208,17 +179,8 @@ describe "Mixlib::Authentication::SignatureVerification" do expect(res).not_to be_nil end - it "should authenticate a normal (post body) request v1.3 SHA1 - Merb" do - mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_3_SHA1, BODY) - expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ) - - service = Mixlib::Authentication::SignatureVerification.new - res = service.authenticate_user_request(mock_request, @user_private_key) - expect(res).not_to be_nil - end - it "should authenticate a normal (post body) request v1.3 SHA256 - Merb" do - mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_3_SHA1, BODY) + mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, MERB_HEADERS_V1_3_SHA256, BODY) expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ) service = Mixlib::Authentication::SignatureVerification.new @@ -307,21 +269,6 @@ describe "Mixlib::Authentication::SignatureVerification" do expect(auth_req).to be_a_valid_content_hash end - it "shouldn't authenticate if the signature is wrong for v1.3 SHA1" do - headers = MERB_HEADERS_V1_3_SHA1.dup - headers["HTTP_X_OPS_AUTHORIZATION_1"] = "epicfail" - mock_request = MockRequest.new(PATH, MERB_REQUEST_PARAMS, headers, BODY) - expect(Time).to receive(:now).at_least(:once).and_return(TIMESTAMP_OBJ) - - auth_req = Mixlib::Authentication::SignatureVerification.new - res = auth_req.authenticate_user_request(mock_request, @user_private_key) - expect(res).to be_nil - expect(auth_req).not_to be_a_valid_request - expect(auth_req).not_to be_a_valid_signature - expect(auth_req).to be_a_valid_timestamp - expect(auth_req).to be_a_valid_content_hash - end - it "shouldn't authenticate if the signature is wrong for v1.3 SHA256" do headers = MERB_HEADERS_V1_3_SHA256.dup headers["HTTP_X_OPS_AUTHORIZATION_1"] = "epicfail" @@ -369,20 +316,6 @@ V1_1_ARGS = { :proto_version => 1.1 } -V1_3_ARGS_SHA1 = { - :body => BODY, - :user_id => USER_ID, - :http_method => :post, - :timestamp => TIMESTAMP_ISO8601, # fixed timestamp so we get back the same answer each time. - :file => MockFile.new, - :path => PATH, - :proto_version => '1.3', - :signing_algorithm => 'sha1', - :headers => { - 'X-OpS-SeRvEr-ApI-VerSiOn' => '1' - } -} - V1_3_ARGS_SHA256 = { :body => BODY, :user_id => USER_ID, @@ -430,15 +363,6 @@ X_OPS_AUTHORIZATION_LINES = [ "FDlbAG7H8Dmvo+wBxmtNkszhzbBnEYtuwQqT8nM/8A==" ] -X_OPS_AUTHORIZATION_LINES_V1_3_SHA1 = [ - "Dh7xqnM3HabvuPVTsJCvHSWGyipvv0xkF9u7XfomC0tDHBF8wG4kEToRI7/1", - "CSa97jlHLQ+VqNq76uy2mxg0PBxPLxPcz+VREJxnxEv+gEEr6MAeMpV97ip0", - "VICuUZ3hPIVNl9hIjmaeOnQSbtJZZOIik0g0O+bpd7AQKa/Y7r2jw42D/Kgg", - "L/ts6ntD2wKb92iPZ5bEXYIJFKVKb7j10PTcHLxkMWd64Cd7GZAdHHl4z8/t", - "VZ5XCe23960z08d2P2I+iYBBCxRCOPwafBvbt0ubls2vecraHQYYXMXovjmV", - "Rxh8xRaTfEhpWwZJa1ONVvsldZlvGiHO/jhmRJ9oCA==" -] - X_OPS_AUTHORIZATION_LINES_V1_3_SHA256 = [ "BjR+iTK2eOgwmT2yGqLvE7Fp+VlpRGyL1dVoF2DmhUPO7EVsnxx2s32AmlOw", "EpaACpav8SoB7K4rpOo3gfBm0XAYLnLLWzcec2OQG2O0wxxHiKVn4qWEe7Cs", @@ -476,19 +400,6 @@ EXPECTED_SIGN_RESULT_V1_1 = { "X-Ops-Timestamp"=>TIMESTAMP_ISO8601 } -EXPECTED_SIGN_RESULT_V1_3_SHA1 = { - "X-Ops-Content-Hash"=>X_OPS_CONTENT_HASH, - "X-Ops-Userid"=>USER_ID, - "X-Ops-Sign"=>"algorithm=sha1;version=1.3;", - "X-Ops-Authorization-1"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[0], - "X-Ops-Authorization-2"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[1], - "X-Ops-Authorization-3"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[2], - "X-Ops-Authorization-4"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[3], - "X-Ops-Authorization-5"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[4], - "X-Ops-Authorization-6"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[5], - "X-Ops-Timestamp"=>TIMESTAMP_ISO8601 -} - EXPECTED_SIGN_RESULT_V1_3_SHA256 = { "X-Ops-Content-Hash"=>X_OPS_CONTENT_HASH_SHA256, "X-Ops-Userid"=>USER_ID, @@ -518,23 +429,6 @@ MERB_REQUEST_PARAMS = { "organization_id"=>"local-test-org", "requesting_actor_id"=>REQUESTING_ACTOR_ID, } -MERB_HEADERS_V1_3_SHA1 = { - # These are used by signatureverification. - "HTTP_HOST"=>"127.0.0.1", - "HTTP_X_OPS_SIGN"=>"algorithm=sha1;version=1.3;", - "HTTP_X_OPS_REQUESTID"=>"127.0.0.1 1258566194.85386", - "HTTP_X_OPS_TIMESTAMP"=>TIMESTAMP_ISO8601, - "HTTP_X_OPS_CONTENT_HASH"=>X_OPS_CONTENT_HASH, - "HTTP_X_OPS_USERID"=>USER_ID, - "HTTP_X_OPS_SERVER_API_VERSION"=>"1", - "HTTP_X_OPS_AUTHORIZATION_1"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[0], - "HTTP_X_OPS_AUTHORIZATION_2"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[1], - "HTTP_X_OPS_AUTHORIZATION_3"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[2], - "HTTP_X_OPS_AUTHORIZATION_4"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[3], - "HTTP_X_OPS_AUTHORIZATION_5"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[4], - "HTTP_X_OPS_AUTHORIZATION_6"=>X_OPS_AUTHORIZATION_LINES_V1_3_SHA1[5], -}.merge(OTHER_HEADERS) - MERB_HEADERS_V1_3_SHA256 = { # These are used by signatureverification. "HTTP_HOST"=>"127.0.0.1", @@ -690,17 +584,6 @@ X-Ops-UserId:#{DIGESTED_USER_ID} EOS V1_1_CANONICAL_REQUEST = V1_1_CANONICAL_REQUEST_DATA.chomp -V1_3_SHA1_CANONICAL_REQUEST_DATA = <