diff --git a/Gemfile b/Gemfile index 6899b36..018d82e 100644 --- a/Gemfile +++ b/Gemfile @@ -60,4 +60,7 @@ group :development, :test do # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] gem "rubocop-rails-omakase", require: false + + # Mocking for tests + gem "mocha" end diff --git a/Gemfile.lock b/Gemfile.lock index 6f4557d..2ee8b55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -132,6 +132,8 @@ GEM marcel (1.0.4) mini_mime (1.1.5) minitest (5.25.1) + mocha (2.5.0) + ruby2_keywords (>= 0.0.5) msgpack (1.7.2) net-http (0.4.1) uri @@ -243,6 +245,7 @@ GEM rubocop-performance rubocop-rails ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) securerandom (0.3.1) sqlite3 (2.2.0-aarch64-linux-gnu) sqlite3 (2.2.0-aarch64-linux-musl) @@ -300,6 +303,7 @@ DEPENDENCIES jbuilder json_tagged_logger jwt + mocha ostruct puma (>= 5.0) rails (~> 7.2.2) diff --git a/app/lib/clients/vault/policy.rb b/app/lib/clients/vault/policy.rb index 15bf6e8..c220b79 100644 --- a/app/lib/clients/vault/policy.rb +++ b/app/lib/clients/vault/policy.rb @@ -29,7 +29,7 @@ def verify_policy(identity, producer_policy_name, consumer_policy_name = nil) # check identity policies sub = identity.sub policies, _ = get_entity_data(sub) - return if policies.any? { |p| p == producer_policy_name } + return if (policies || []).any? { |p| p == producer_policy_name } # check group membership in consumer policy if given if consumer_policy_name.present? diff --git a/test/lib/clients/vault/policy_test.rb b/test/lib/clients/vault/policy_test.rb new file mode 100644 index 0000000..d8d3f7e --- /dev/null +++ b/test/lib/clients/vault/policy_test.rb @@ -0,0 +1,43 @@ +require "test_helper" + +class PolicyTest < ActiveSupport::TestCase + setup do + @client = Clients::Vault + @identity = Identity.new + email = SecureRandom.hex(4) + @identity.sub = email + end + + test "#verify_policy raises when identity does not have the policy" do + policy_name = "some/policy/name" + @client.expects(:get_entity_data).with(@identity.sub).returns([ [ "some/other/policy" ], nil ]) + err = assert_raises { @client.verify_policy(@identity, policy_name) } + assert_kind_of AuthError, err + end + + test "#verify_policy permits identity having the policy" do + policy_name = "some/policy/name" + @client.expects(:get_entity_data).with(@identity.sub).returns([ [ policy_name ], nil ]) + assert_nil @client.verify_policy(@identity, policy_name) + end + + test "#verify_policy looks for a role corresponding to consumer policy when supplied" do + producer_policy = "some/policy/name" + consumer_policy = "some/policy/other" + read_oidc_response = OpenStruct.new(data: { bound_claims: { groups: [ "my-group" ] } }) + @client.expects(:get_entity_data).with(@identity.sub).returns([ [], nil ]) + @client.expects(:read_oidc_role).with("some_policy_other-role").returns(read_oidc_response) + err = assert_raises { @client.verify_policy(@identity, producer_policy, consumer_policy) } + assert_kind_of AuthError, err + end + + test "#verify_policy permits identity having group linked to consumer policy role" do + producer_policy = "some/policy/name" + consumer_policy = "some/policy/other" + @identity.groups = [ "my-group" ] + read_oidc_response = OpenStruct.new(data: { bound_claims: { groups: [ "my-group" ] } }) + @client.expects(:get_entity_data).with(@identity.sub).returns([ [], nil ]) + @client.expects(:read_oidc_role).with("some_policy_other-role").returns(read_oidc_response) + assert_nil @client.verify_policy(@identity, producer_policy, consumer_policy) + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index d5cdb9d..124da9e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,6 +2,8 @@ require_relative "../config/environment" require "rails/test_help" require "minitest/mock" +require "minitest/spec" +require "mocha/minitest" module ActiveSupport class TestCase