From e3a880a9f9df56863b34351bab0ceac53fb99fef Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Wed, 17 May 2017 09:12:13 -0700 Subject: [PATCH 1/4] Add a #token_ttl method so we can sense ttl values --- lib/token_manager.rb | 4 ++++ spec/lib/token_manager_spec.rb | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 spec/lib/token_manager_spec.rb diff --git a/lib/token_manager.rb b/lib/token_manager.rb index 2ffe456a3b6..1e8d3fae46a 100644 --- a/lib/token_manager.rb +++ b/lib/token_manager.rb @@ -48,6 +48,10 @@ def invalidate_token(token) token_store.delete(token) end + def token_ttl + @options[:token_ttl] + end + private def token_store diff --git a/spec/lib/token_manager_spec.rb b/spec/lib/token_manager_spec.rb new file mode 100644 index 00000000000..4796c676107 --- /dev/null +++ b/spec/lib/token_manager_spec.rb @@ -0,0 +1,15 @@ +RSpec.describe TokenManager do + describe "#token_ttl" do + it "returns the ttl" do + token_manager = described_class.new(described_class::DEFAULT_NS, :token_ttl => 60) + + expect(token_manager.token_ttl).to eq(60) + end + + it "defaults to 10 minutes" do + token_manager = described_class.new + + expect(token_manager.token_ttl).to eq(600) + end + end +end From e47f599601c45bd7a203cf8605d39d891da50730 Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Wed, 17 May 2017 09:14:09 -0700 Subject: [PATCH 2/4] s/token_ttl/ttl/ so as not to confused with #token_ttl --- lib/token_manager.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/token_manager.rb b/lib/token_manager.rb index 1e8d3fae46a..9497bee1e93 100644 --- a/lib/token_manager.rb +++ b/lib/token_manager.rb @@ -14,8 +14,8 @@ def initialize(namespace = DEFAULT_NS, options = {}) def gen_token(token_options = {}) token = SecureRandom.hex(16) - token_ttl = token_options.delete(:token_ttl_override) || @options[:token_ttl] - token_data = {:token_ttl => token_ttl, :expires_on => Time.now.utc + token_ttl} + ttl = token_options.delete(:token_ttl_override) || @options[:token_ttl] + token_data = {:token_ttl => ttl, :expires_on => Time.now.utc + ttl} token_store.write(token, token_data.merge!(prune_token_options(token_options)), @@ -27,11 +27,11 @@ def reset_token(token) token_data = token_store.read(token) return {} if token_data.nil? - token_ttl = token_data[:token_ttl] - token_data[:expires_on] = Time.now.utc + token_ttl + ttl = token_data[:token_ttl] + token_data[:expires_on] = Time.now.utc + ttl token_store.write(token, token_data, - :expires_in => token_ttl) + :expires_in => ttl) end def token_get_info(token, what = nil) From 49cf6aa182905968987b9ba0f3cab0dadc07f646 Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Wed, 17 May 2017 09:15:14 -0700 Subject: [PATCH 3/4] Use the wrapped #token_ttl instead of going through @options --- lib/token_manager.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/token_manager.rb b/lib/token_manager.rb index 9497bee1e93..1994dc8eebf 100644 --- a/lib/token_manager.rb +++ b/lib/token_manager.rb @@ -14,12 +14,12 @@ def initialize(namespace = DEFAULT_NS, options = {}) def gen_token(token_options = {}) token = SecureRandom.hex(16) - ttl = token_options.delete(:token_ttl_override) || @options[:token_ttl] + ttl = token_options.delete(:token_ttl_override) || token_ttl token_data = {:token_ttl => ttl, :expires_on => Time.now.utc + ttl} token_store.write(token, token_data.merge!(prune_token_options(token_options)), - :expires_in => @options[:token_ttl]) + :expires_in => token_ttl) token end @@ -55,7 +55,7 @@ def token_ttl private def token_store - TokenStore.acquire(@namespace, @options[:token_ttl]) + TokenStore.acquire(@namespace, token_ttl) end def prune_token_options(token_options = {}) From 9fa3858d7cbdb8c285045c9fb200a5c3ad5a6cd9 Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Wed, 17 May 2017 09:25:14 -0700 Subject: [PATCH 4/4] Make token_ttl callable (evaluated at call time) If we pass in a value that can change (i.e. settings), it's evaluated once at construction time and will never change. Thus, if a user changes the session time out setting, a restart of the server is required. By making this value callable we can delay evaluation until call time, which honors updated settings values. Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1451848 --- lib/services/api/user_token_service.rb | 4 ++-- lib/token_manager.rb | 4 ++-- spec/lib/token_manager_spec.rb | 11 ++++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/services/api/user_token_service.rb b/lib/services/api/user_token_service.rb index a48eb6a3e6d..9ee6987310e 100644 --- a/lib/services/api/user_token_service.rb +++ b/lib/services/api/user_token_service.rb @@ -15,7 +15,7 @@ def token_mgr(type) when 'api', 'ui' # The default API token and UI token share the same TokenStore @token_mgr['api'] ||= new_token_mgr(base_config[:module], base_config[:name], api_config) when 'ws' - @token_mgr['ws'] ||= TokenManager.new('ws', :token_ttl => ::Settings.session.timeout) + @token_mgr['ws'] ||= TokenManager.new('ws', :token_ttl => -> { ::Settings.session.timeout }) end end @@ -55,7 +55,7 @@ def new_token_mgr(mod, name, api_config) token_ttl = api_config[:token_ttl] options = {} - options[:token_ttl] = token_ttl.to_i_with_method if token_ttl + options[:token_ttl] = -> { token_ttl.to_i_with_method } if token_ttl log_init(mod, name, options) if @svc_options[:log_init] TokenManager.new(mod, options) diff --git a/lib/token_manager.rb b/lib/token_manager.rb index 1994dc8eebf..8b75ad0e8c6 100644 --- a/lib/token_manager.rb +++ b/lib/token_manager.rb @@ -9,7 +9,7 @@ class TokenManager def initialize(namespace = DEFAULT_NS, options = {}) @namespace = namespace - @options = {:token_ttl => 10.minutes}.merge(options) + @options = {:token_ttl => -> { 10.minutes }}.merge(options) end def gen_token(token_options = {}) @@ -49,7 +49,7 @@ def invalidate_token(token) end def token_ttl - @options[:token_ttl] + @options[:token_ttl].call end private diff --git a/spec/lib/token_manager_spec.rb b/spec/lib/token_manager_spec.rb index 4796c676107..32bffba6fed 100644 --- a/spec/lib/token_manager_spec.rb +++ b/spec/lib/token_manager_spec.rb @@ -1,7 +1,7 @@ RSpec.describe TokenManager do describe "#token_ttl" do it "returns the ttl" do - token_manager = described_class.new(described_class::DEFAULT_NS, :token_ttl => 60) + token_manager = described_class.new(described_class::DEFAULT_NS, :token_ttl => -> { 60 }) expect(token_manager.token_ttl).to eq(60) end @@ -11,5 +11,14 @@ expect(token_manager.token_ttl).to eq(600) end + + it "evaluates at call time" do + stub_settings(:session => {:timeout => 60}) + token_manager = described_class.new(described_class::DEFAULT_NS, :token_ttl => -> { Settings.session.timeout }) + + stub_settings(:session => {:timeout => 120}) + + expect(token_manager.token_ttl).to eq(120) + end end end