fix recursion loop

refs INTEROP-8632

Test plan
- Change the constant in DeveloperKey::DEFAULT_KEY_NAME
- restart your docker container for good measure
- run DeveloperKey.default in a console (might have to do dc down && dc
  up)
- there should be no infinite loop. a new Dk should have been reated.
- hard-delete the new key (DK.where(id: DK.default).delete_all), undo
  your DEFAULT_KEY_NAME code change
- restart your docker container for good measure
- try to turn off the default DK account binding in the UI, it won't let
  you (original protection change)

Change-Id: I7a41435cd0c0eda7fa552bae0be4adfd261b9e10
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/354641
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Steven McGee <steve.mcgee@instructure.com>
QA-Review: Steven McGee <steve.mcgee@instructure.com>
Product-Review: Evan Battaglia <ebattaglia@instructure.com>
This commit is contained in:
Evan Battaglia 2024-08-08 16:22:56 -02:30
parent 9d4a265cfd
commit 84e5e57356
4 changed files with 40 additions and 8 deletions

View File

@ -177,11 +177,11 @@ class DeveloperKey < ActiveRecord::Base
end
class << self
def default
get_special_key(DeveloperKey::DEFAULT_KEY_NAME)
def default(create_if_missing: true)
get_special_key(DeveloperKey::DEFAULT_KEY_NAME, create_if_missing:)
end
def get_special_key(default_key_name)
def get_special_key(default_key_name, create_if_missing: true)
Shard.birth.activate do
@special_keys ||= {}
@ -192,6 +192,7 @@ class DeveloperKey < ActiveRecord::Base
key = DeveloperKey.where(id: key_id).first
end
return @special_keys[default_key_name] = key if key
return nil unless create_if_missing
key = DeveloperKey.create!(name: default_key_name)
key.developer_key_account_bindings.update_all(workflow_state: "on")

View File

@ -123,16 +123,19 @@ class DeveloperKeyAccountBinding < ApplicationRecord
private
def for_default_key?
developer_key&.name == DeveloperKey::DEFAULT_KEY_NAME &&
developer_key == DeveloperKey.default(create_if_missing: false)
end
# DeveloperKey.default is for user-generated tokens and must always be ON
def enable_default_key
if developer_key.name == DeveloperKey::DEFAULT_KEY_NAME && developer_key == DeveloperKey.default
self.workflow_state = :on
end
self.workflow_state = :on if !on? && for_default_key?
end
# DeveloperKey.default is for user-generated tokens and must always be ON
def protect_default_key_binding
raise "Please don't turn off the default developer key" if developer_key.name == DeveloperKey::DEFAULT_KEY_NAME && developer_key == DeveloperKey.default && !on?
raise "Please don't turn off the default developer key" if !on? && for_default_key?
end
def update_lti_registration_account_binding

View File

@ -1186,6 +1186,26 @@ describe DeveloperKey do
end
describe "default" do
context "when create_if_missing: false is passed" do
before do
allow(DeveloperKey).to receive(:get_special_key) do |*args, **kwargs|
DeveloperKey.original_get_special_key(*args, **kwargs)
end
end
it "does not create a key" do
DeveloperKey.delete_all
expect(DeveloperKey.count).to eq 0
DeveloperKey.default(create_if_missing: false)
expect(DeveloperKey.count).to eq 0
end
it "finds existing keys" do
expect(DeveloperKey.default).to_not be_nil
expect(DeveloperKey.default(create_if_missing: false)).to_not be_nil
end
end
context "sharding" do
specs_require_sharding

View File

@ -1027,12 +1027,20 @@ Shoulda::Matchers.configure do |config|
end
module DeveloperKeyStubs
def get_special_key(default_key_name)
@@original_get_special_key = DeveloperKey.method(:get_special_key)
def original_get_special_key(*args, **kwargs)
@@original_get_special_key.call(*args, **kwargs)
end
def get_special_key(default_key_name, create_if_missing: true)
Shard.birth.activate do
@special_keys ||= {}
# TODO: we have to do this because tests run in transactions
testkey = DeveloperKey.where(name: default_key_name).first_or_initialize
return nil if testkey.new_record? && !create_if_missing
testkey.auto_expire_tokens = false if testkey.new_record?
testkey.sns_arn = "arn:aws:s3:us-east-1:12345678910:foo/bar"
testkey.save! if testkey.changed?