From f60a51e0284903e8ae14656c19bd2d3adeff73cd Mon Sep 17 00:00:00 2001 From: Weslley Almeida Date: Wed, 14 Feb 2024 14:52:52 -0300 Subject: [PATCH 1/5] [WOR-4059] - Upgrade to ruby 3.2.3 - Upgrade rspec gem and fix specs - Dockerfile and docker compose --- .bundle/config | 2 + Dockerfile | 21 +++++++ Gemfile.lock | 30 ++++++---- docker-compose.dev.yml | 16 ++++++ signature.gemspec | 2 +- spec/signature_spec.rb | 122 ++++++++++++++++++++--------------------- 6 files changed, 120 insertions(+), 73 deletions(-) create mode 100644 .bundle/config create mode 100644 Dockerfile create mode 100644 docker-compose.dev.yml diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 0000000..846e178 --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_BUILD__EVENTMACHINE: "--with-openssl-dir=/opt/homebrew/opt/openssl@3" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d129ebc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM public.ecr.aws/docker/library/ruby:3.2.3-alpine3.19 + +RUN apk add --no-cache --update git build-base bash + + +RUN echo "#!/bin/sh" >> /entrypoint.sh && \ + echo 'exec "$@"' >>/entrypoint.sh && \ + chmod +x /entrypoint.sh +COPY signature.gemspec Gemfile Gemfile.lock /app/ +COPY lib/signature/version.rb /app/lib/signature/ + +WORKDIR /app + +RUN gem update --system 3.3.26 +RUN gem install bundler:2.4.22 + +RUN bundle install + +COPY . /app/ + +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] diff --git a/Gemfile.lock b/Gemfile.lock index b107762..0abf67d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,27 +1,32 @@ PATH remote: . specs: - signature (0.1.8) + signature (0.1.9) GEM remote: https://rubygems.org/ specs: bacon (1.2.0) - diff-lcs (1.2.4) + diff-lcs (1.5.1) em-spec (0.2.6) bacon eventmachine rspec (> 2.6.0) test-unit eventmachine (1.0.7) - rspec (2.13.0) - rspec-core (~> 2.13.0) - rspec-expectations (~> 2.13.0) - rspec-mocks (~> 2.13.0) - rspec-core (2.13.1) - rspec-expectations (2.13.0) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.13.1) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.0) test-unit (2.5.4) PLATFORMS @@ -29,5 +34,8 @@ PLATFORMS DEPENDENCIES em-spec - rspec + rspec (~> 3.13.0) signature! + +BUNDLED WITH + 2.4.22 diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..3d9bf02 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,16 @@ +version: '3.5' + +services: + signature: + stdin_open: true + build: + dockerfile: Dockerfile + context: . + volumes: + - .:/app + command: "bash -c 'while true; do sleep 2; done'" + logging: &default-logging-options + driver: json-file + options: + max-size: "20m" + max-file: "5" diff --git a/signature.gemspec b/signature.gemspec index 13a87ae..1fbe6fa 100644 --- a/signature.gemspec +++ b/signature.gemspec @@ -21,6 +21,6 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.add_dependency "jruby-openssl" if defined?(JRUBY_VERSION) - s.add_development_dependency "rspec" + s.add_development_dependency "rspec", "~> 3.13.0" s.add_development_dependency "em-spec" end diff --git a/spec/signature_spec.rb b/spec/signature_spec.rb index 96256cd..983e47b 100644 --- a/spec/signature_spec.rb +++ b/spec/signature_spec.rb @@ -2,7 +2,7 @@ describe Signature do before :each do - Time.stub!(:now).and_return(Time.at(1234)) + allow(Time).to receive(:now).and_return(1234) @token = Signature::Token.new('key', 'secret') @@ -20,28 +20,26 @@ it "should generate signature correctly" do @request.sign(@token) string = @request.send(:string_to_sign) - string.should == "POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params" + expect(string).to eq("POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params") digest = OpenSSL::Digest::SHA256.new signature = OpenSSL::HMAC.hexdigest(digest, @token.secret, string) - signature.should == @signature + expect(signature).to eq(@signature) end it "should make auth_hash available after request is signed" do @request.query_hash = { "query" => "params" } - lambda { - @request.auth_hash - }.should raise_error('Request not signed') + expect { @request.auth_hash }.to raise_error('Request not signed') @request.sign(@token) - @request.auth_hash.should == { + expect(@request.auth_hash).to eq({ :auth_signature => "da078fcedd72941b6c873caa40d0d6b2000ebfc700cee802b128dd20f72e74e9", :auth_version => "1.0", :auth_key => "key", :auth_timestamp => '1234' - } + }) end it "should cope with symbol keys" do @@ -49,7 +47,7 @@ :query => "params", :go => "here" } - @request.sign(@token)[:auth_signature].should == @signature + expect(@request.sign(@token)[:auth_signature]).to eq(@signature) end it "should cope with upcase keys (keys are lowercased before signing)" do @@ -57,31 +55,33 @@ "Query" => "params", "GO" => "here" } - @request.sign(@token)[:auth_signature].should == @signature + expect(@request.sign(@token)[:auth_signature]).to eq(@signature) end it "should generate correct string when query hash contains array" do @request.query_hash = { "things" => ["thing1", "thing2"] } - @request.send(:string_to_sign).should == "POST\n/some/path\nthings[]=thing1&things[]=thing2" + expect(@request.send(:string_to_sign)).to eq("POST\n/some/path\nthings[]=thing1&things[]=thing2") end it "should generate correct string when query hash contains nested elements" do @request.query_hash = { "things" => [{ "thing_1" => "value1" }, { "thing_2" => "value2" }] } - @request.send(:string_to_sign).should == + expect(@request.send(:string_to_sign)).to eq( "POST\n/some/path\nthings[][thing_1]=value1&things[][thing_2]=value2" + ) end it "should generate correct string when query hash contains nested arrays" do @request.query_hash = { "things" => [{ "thing_1" => [["v1", "v1"]] }, { "thing_2" => [["v2", "v2"]] }] } - @request.send(:string_to_sign).should == + expect(@request.send(:string_to_sign)).to eq( "POST\n/some/path\nthings[][thing_1][][]=v1&things[][thing_1][][]=v1"\ "&things[][thing_2][][]=v2&things[][thing_2][][]=v2" + ) end # This may well change in auth version 2 @@ -89,26 +89,26 @@ @request.query_hash = { "key;" => "value@" } - @request.send(:string_to_sign).should == "POST\n/some/path\nkey;=value@" + expect(@request.send(:string_to_sign)).to eq("POST\n/some/path\nkey;=value@") end it "should cope with requests where the value is nil (antiregression)" do @request.query_hash = { "key" => nil } - @request.send(:string_to_sign).should == "POST\n/some/path\nkey=" + expect(@request.send(:string_to_sign)).to eq("POST\n/some/path\nkey=") end it "should use the path to generate signature" do @request.path = '/some/other/path' - @request.sign(@token)[:auth_signature].should_not == @signature + expect(@request.sign(@token)[:auth_signature]).not_to eq(@signature) end it "should use the query string keys to generate signature" do @request.query_hash = { "other" => "query" } - @request.sign(@token)[:auth_signature].should_not == @signature + expect(@request.sign(@token)[:auth_signature]).not_to eq(@signature) end it "should use the query string values to generate signature" do @@ -116,7 +116,7 @@ "key" => "notfoo", "other" => 'bar' } - @request.sign(@token)[:signature].should_not == @signature + expect(@request.sign(@token)[:signature]).not_to eq(@signature) end end @@ -128,112 +128,112 @@ it "should verify requests" do request = Signature::Request.new('POST', '/some/path', @params) - request.authenticate_by_token(@token).should == true + expect(request.authenticate_by_token(@token)).to eq(true) end it "should raise error if signature is not correct" do @params[:auth_signature] = 'asdf' request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate_by_token!(@token) - }.should raise_error('Invalid signature: you should have sent HmacSHA256Hex("POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params", your_secret_key), but you sent "asdf"') + }.to raise_error('Invalid signature: you should have sent HmacSHA256Hex("POST\n/some/path\nauth_key=key&auth_timestamp=1234&auth_version=1.0&go=here&query=params", your_secret_key), but you sent "asdf"') end it "should raise error if timestamp not available" do @params.delete(:auth_timestamp) request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate_by_token!(@token) - }.should raise_error('Timestamp required') + }.to raise_error('Timestamp required') end it "should raise error if timestamp has expired (default of 600s)" do request = Signature::Request.new('POST', '/some/path', @params) - Time.stub!(:now).and_return(Time.at(1234 + 599)) - request.authenticate_by_token!(@token).should == true - Time.stub!(:now).and_return(Time.at(1234 - 599)) - request.authenticate_by_token!(@token).should == true - Time.stub!(:now).and_return(Time.at(1234 + 600)) - lambda { + allow(Time).to receive(:now).and_return(Time.at(1234 + 599)) + expect(request.authenticate_by_token!(@token)).to eq(true) + allow(Time).to receive(:now).and_return(Time.at(1234 - 599)) + expect(request.authenticate_by_token!(@token)).to eq(true) + allow(Time).to receive(:now).and_return(Time.at(1234 + 600)) + expect { request.authenticate_by_token!(@token) - }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:30:34Z)") - Time.stub!(:now).and_return(Time.at(1234 - 600)) - lambda { + }.to raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:30:34Z)") + allow(Time).to receive(:now).and_return(Time.at(1234 - 600)) + expect { request.authenticate_by_token!(@token) - }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:10:34Z)") + }.to raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 600s of server time (1970-01-01T00:10:34Z)") end it "should be possible to customize the timeout grace period" do grace = 10 request = Signature::Request.new('POST', '/some/path', @params) - Time.stub!(:now).and_return(Time.at(1234 + grace - 1)) - request.authenticate_by_token!(@token, grace).should == true - Time.stub!(:now).and_return(Time.at(1234 + grace)) - lambda { + allow(Time).to receive(:now).and_return(Time.at(1234 + grace - 1)) + expect(request.authenticate_by_token!(@token, grace)).to eq(true) + allow(Time).to receive(:now).and_return(Time.at(1234 + grace)) + expect { request.authenticate_by_token!(@token, grace) - }.should raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 10s of server time (1970-01-01T00:20:44Z)") + }.to raise_error("Timestamp expired: Given timestamp (1970-01-01T00:20:34Z) not within 10s of server time (1970-01-01T00:20:44Z)") end it "should be possible to skip timestamp check by passing nil" do request = Signature::Request.new('POST', '/some/path', @params) - Time.stub!(:now).and_return(Time.at(1234 + 1000)) - request.authenticate_by_token!(@token, nil).should == true + allow(Time).to receive(:now).and_return(Time.at(1234 + 1000)) + expect(request.authenticate_by_token!(@token, nil)).to eq(true) end - + it "should check that auth_version is supplied" do @params.delete(:auth_version) request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate_by_token!(@token) - }.should raise_error('Version required') + }.to raise_error('Version required') end it "should check that auth_version equals 1.0" do @params[:auth_version] = '1.1' request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate_by_token!(@token) - }.should raise_error('Version not supported') + }.to raise_error('Version not supported') end it "should validate that the provided token has a non-empty secret" do token = Signature::Token.new('key', '') request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate_by_token!(token) - }.should raise_error('Provided token is missing secret') + }.to raise_error('Provided token is missing secret') end describe "when used with optional block" do it "should optionally take a block which yields the signature" do request = Signature::Request.new('POST', '/some/path', @params) - request.authenticate do |key| - key.should == @token.key + expect(request.authenticate do |key| + expect(key).to eq(@token.key) @token - end.should == @token + end).to eq(@token) end it "should raise error if no auth_key supplied to request" do @params.delete(:auth_key) request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate { |key| nil } - }.should raise_error('Missing parameter: auth_key') + }.to raise_error('Missing parameter: auth_key') end it "should raise error if block returns nil (i.e. key doesn't exist)" do request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate { |key| nil } - }.should raise_error('Unknown auth_key') + }.to raise_error('Unknown auth_key') end it "should raise unless block given" do request = Signature::Request.new('POST', '/some/path', @params) - lambda { + expect { request.authenticate - }.should raise_error(ArgumentError, "Block required") + }.to raise_error(ArgumentError, "Block required") end end @@ -253,7 +253,7 @@ df.succeed(@token) request_df.callback { |token| - token.should == @token + expect(token).to eq(@token) done } } @@ -271,8 +271,8 @@ df.fail() request_df.errback { |e| - e.class.should == Signature::AuthenticationError - e.message.should == 'Unknown auth_key' + expect(e.class).to eq(Signature::AuthenticationError) + expect(e.message).to eq('Unknown auth_key') done } } @@ -291,8 +291,8 @@ df.succeed(token) request_df.errback { |e| - e.class.should == Signature::AuthenticationError - e.message.should =~ /Invalid signature/ + expect(e.class).to eq(Signature::AuthenticationError) + expect(e.message).to match(/Invalid signature/) done } } From 2d6a878613d4f2381539cc6e21af186fd21615c8 Mon Sep 17 00:00:00 2001 From: Weslley Almeida Date: Thu, 15 Feb 2024 10:10:07 -0300 Subject: [PATCH 2/5] - clean up --- .bundle/config | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .bundle/config diff --git a/.bundle/config b/.bundle/config deleted file mode 100644 index 846e178..0000000 --- a/.bundle/config +++ /dev/null @@ -1,2 +0,0 @@ ---- -BUNDLE_BUILD__EVENTMACHINE: "--with-openssl-dir=/opt/homebrew/opt/openssl@3" From 809f92318650508ee030f150a927ba17525218e7 Mon Sep 17 00:00:00 2001 From: Weslley Almeida Date: Thu, 15 Feb 2024 10:14:24 -0300 Subject: [PATCH 3/5] - change version --- Gemfile.lock | 2 +- lib/signature/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0abf67d..2030e6d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - signature (0.1.9) + signature (1.0.0) GEM remote: https://rubygems.org/ diff --git a/lib/signature/version.rb b/lib/signature/version.rb index 5a6732d..559570e 100644 --- a/lib/signature/version.rb +++ b/lib/signature/version.rb @@ -1,3 +1,3 @@ module Signature - VERSION = "0.1.9" + VERSION = "1.0.0" end From 8f6a486304e320b0250aa7630fa73a8af20d7d9e Mon Sep 17 00:00:00 2001 From: Weslley Almeida Date: Mon, 19 Feb 2024 16:05:34 -0300 Subject: [PATCH 4/5] fix gem version --- lib/signature/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/signature/version.rb b/lib/signature/version.rb index 559570e..2ea5351 100644 --- a/lib/signature/version.rb +++ b/lib/signature/version.rb @@ -1,3 +1,3 @@ module Signature - VERSION = "1.0.0" + VERSION = "0.2.0" end From 070801097a96c2292eec8469877b065ca5605eb9 Mon Sep 17 00:00:00 2001 From: Weslley Almeida Date: Mon, 19 Feb 2024 17:10:05 -0300 Subject: [PATCH 5/5] fix gemfile.lock --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2030e6d..c6ef2cc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - signature (1.0.0) + signature (0.2.0) GEM remote: https://rubygems.org/ @@ -38,4 +38,4 @@ DEPENDENCIES signature! BUNDLED WITH - 2.4.22 + 2.5.6