diff --git a/config/initializers/app_artifacts.rb b/config/initializers/app_artifacts.rb index d9486fc409b..2f82b258b3a 100644 --- a/config/initializers/app_artifacts.rb +++ b/config/initializers/app_artifacts.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'app_artifacts' +require 'openid_connect_key_validation' AppArtifacts.setup do |store| # When adding or removing certs, make sure to update the 'saml_endpoint_configs' config @@ -12,3 +13,9 @@ store.add_artifact(:oidc_private_key, '/%s/oidc.key') { |k| OpenSSL::PKey::RSA.new(k) } store.add_artifact(:oidc_public_key, '/%s/oidc.pub') { |k| OpenSSL::PKey::RSA.new(k) } end + +valid = OpenidConnectKeyValidation.valid?( + public_key: AppArtifacts.store.oidc_public_key, + private_key: AppArtifacts.store.oidc_private_key, +) +raise 'OIDC Public/Private Keys do not match' if !valid diff --git a/lib/openid_connect_key_validation.rb b/lib/openid_connect_key_validation.rb new file mode 100644 index 00000000000..53fd5f2c8d3 --- /dev/null +++ b/lib/openid_connect_key_validation.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class OpenidConnectKeyValidation + # @param [private_key] OpenSSL::PKey + # @param [public_key] OpenSSL::PKey + def self.valid?(private_key:, public_key:, data: 'abc123') + signature = private_key.sign('SHA256', data) + public_key.verify('SHA256', signature, data) + end +end diff --git a/spec/lib/openid_connect_key_validation_spec.rb b/spec/lib/openid_connect_key_validation_spec.rb new file mode 100644 index 00000000000..d8f21c99e26 --- /dev/null +++ b/spec/lib/openid_connect_key_validation_spec.rb @@ -0,0 +1,41 @@ +require 'rails_helper' + +RSpec.describe OpenidConnectKeyValidation do + let(:private_key) { OpenSSL::PKey::RSA.generate(1_024) } + + describe '#valid?' do + it 'returns true for a valid public/private key pair' do + public_key = private_key.public_key + valid = OpenidConnectKeyValidation.valid?( + private_key: private_key, + public_key: public_key, + data: '123', + ) + + expect(valid).to eq(true) + end + + it 'returns false for a invalid pair' do + other_private_key = OpenSSL::PKey::RSA.generate(1_024) + public_key = private_key.public_key + valid = OpenidConnectKeyValidation.valid?( + private_key: other_private_key, + public_key: public_key, + data: '123', + ) + + expect(valid).to eq(false) + end + + it 'raises an error if private key and public key are swapped' do + public_key = private_key.public_key + expect do + OpenidConnectKeyValidation.valid?( + private_key: public_key, + public_key: private_key, + data: '123', + ).to raise_error(RuntimeError.new('private key is needed')) + end + end + end +end