Skip to content

Commit

Permalink
Merge pull request ManageIQ#13966 from carbonin/remove_central_admin_…
Browse files Browse the repository at this point in the history
…enable

Remove the mechanisms around "configuring" central admin
  • Loading branch information
gtanzillo authored Feb 20, 2017
2 parents 390b0fe + 37f854e commit 33c19ae
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 211 deletions.
66 changes: 1 addition & 65 deletions app/models/miq_region.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class MiqRegion < ApplicationRecord
after_save :clear_my_region_cache

acts_as_miq_taggable
include AuthenticationMixin
include UuidMixin
include NamingSequenceMixin
include AggregationMixin
Expand All @@ -32,7 +31,6 @@ class MiqRegion < ApplicationRecord
alias_method :all_storages, :storages

PERF_ROLLUP_CHILDREN = [:ext_management_systems, :storages]
AUTHENTICATION_TYPE = "system_api".freeze

def database_backups
DatabaseBackup.in_region(region_number)
Expand Down Expand Up @@ -244,69 +242,13 @@ def remote_ws_url
hostname && URI::HTTPS.build(:host => hostname).to_s
end

def generate_auth_key_queue(ssh_user, ssh_password, ssh_host = nil)
args = [ssh_user, MiqPassword.try_encrypt(ssh_password)]
args << ssh_host if ssh_host

MiqQueue.put_unless_exists(
:class_name => self.class.name,
:instance_id => id,
:queue_name => "generic",
:method_name => "generate_auth_key",
:args => args
)
end

def generate_auth_key(ssh_user, ssh_password, ssh_host = remote_ws_address)
key = remote_region_v2_key(ssh_user, MiqPassword.try_decrypt(ssh_password), ssh_host)

auth = AuthToken.new
auth.auth_key = key
auth.name = "Region #{region} API Key"
auth.resource = self
auth.authtype = AUTHENTICATION_TYPE
auth.save!
end

def remove_auth_key
authentication_delete(AUTHENTICATION_TYPE)
end

def verify_credentials(_auth_type = nil, _options = nil)
# TODO: verify the key against the remote api using the api client gem
true
end

def auth_key_configured?
authentication_token(AUTHENTICATION_TYPE).present?
end

def api_system_auth_token(userid)
token_hash = {
:server_guid => remote_ws_miq_server.guid,
:userid => userid,
:timestamp => Time.now.utc
}
encrypt(token_hash.to_yaml)
end

def required_credential_fields(_type)
[:auth_key]
end

def encrypt(string)
region_v2_key = authentication_token(AUTHENTICATION_TYPE)
raise "No key configured for region #{region}. Configure Central Admin to fetch the key" if region_v2_key.nil?

file = Tempfile.new("region_auth_key")
begin
file.write(region_v2_key)
file.close
key = EzCrypto::Key.load(file.path)
MiqPassword.new.encrypt(string, "v2", key)
ensure
file.unlink
end
MiqPassword.encrypt(token_hash.to_yaml)
end

def self.api_system_auth_token_for_region(region_id, user)
Expand Down Expand Up @@ -392,10 +334,4 @@ def perf_capture_always=(options)
def clear_my_region_cache
MiqRegion.my_region_clear_cache
end

def remote_region_v2_key(ssh_user, ssh_password, ssh_host)
require 'net/scp'
key_path = "/var/www/miq/vmdb/certs/v2_key"
Net::SCP.download!(ssh_host, ssh_user, key_path, nil, :ssh => {:password => ssh_password})
end
end
5 changes: 0 additions & 5 deletions app/models/mixins/inter_region_api_method_relay.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ def api_relay_class_method(method, action = method)
def self.api_client_connection_for_region(region_number, user = User.current_userid)
region = MiqRegion.find_by(:region => region_number)

unless region.auth_key_configured?
_log.error("Region #{region_number} is not configured for central administration")
raise "Region #{region_number} is not configured for central administration"
end

url = region.remote_ws_url
if url.nil?
_log.error("The remote region [#{region_number}] does not have a web service address.")
Expand Down
1 change: 0 additions & 1 deletion app/models/pglogical_subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ def self.save_all!(subscription_list)

def delete
pglogical.subscription_drop(id, true)
MiqRegion.find_by_region(provider_region).remove_auth_key
MiqRegion.destroy_region(connection, provider_region)
if self.class.count == 0
pglogical.node_drop(MiqPglogical.local_node_name, true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class RemoveCentralAdminRegionAuthRecords < ActiveRecord::Migration[5.0]
class Authentication < ActiveRecord::Base; end

def up
Authentication.where(:resource_type => 'MiqRegion').delete_all
end
end
2 changes: 0 additions & 2 deletions spec/factories/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,4 @@
factory :ansible_network_credential,
:parent => :automation_manager_authentication,
:class => "ManageIQ::Providers::AnsibleTower::AutomationManager::NetworkCredential"

factory :auth_token, :class => "AuthToken"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require_migration

describe RemoveCentralAdminRegionAuthRecords do
let(:authentication_stub) { migration_stub(:Authentication) }

migration_context :up do
it "removes rows that point to MiqRegion" do
authentication_stub.create!(:resource_type => "MiqRegion")
authentication_stub.create!(:resource_type => "MiqRegion")
authentication_stub.create!(:resource_type => "Provider")

migrate

expect(authentication_stub.count).to eq(1)
expect(authentication_stub.first.resource_type).to eq("Provider")
end
end
end
90 changes: 0 additions & 90 deletions spec/models/miq_region_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,76 +154,10 @@
end
end

describe "#generate_auth_key" do
let(:remote_region) { FactoryGirl.create(:miq_region) }
let(:remote_key) { "this is the encryption key!" }

before { EvmSpecHelper.create_guid_miq_server_zone }

it "stores an authentication key" do
require 'net/scp'
host = "remote-region.example.com"
password = "mypassword"
user = "admin"

expect(Net::SCP).to receive(:download!)
.with(host, user, "/var/www/miq/vmdb/certs/v2_key", nil, :ssh => {:password => password})
.and_return(remote_key)

remote_region.generate_auth_key(user, password, host)

expect(remote_region.authentication_token("system_api")).to eq(remote_key)
end
end

describe "#auth_key_configured?" do
let(:remote_region) { FactoryGirl.create(:miq_region) }
let(:remote_key) { "this is the encryption key!" }

before { EvmSpecHelper.create_guid_miq_server_zone }

it "returns true if a key is configured" do
FactoryGirl.create(
:auth_token,
:resource_id => remote_region.id,
:resource_type => "MiqRegion",
:auth_key => remote_key
)

expect(remote_region.auth_key_configured?).to be true
end

it "returns false if a key is not configured" do
expect(remote_region.auth_key_configured?).to be false
end
end

describe "#remove_auth_key" do
let(:remote_region) { FactoryGirl.create(:miq_region) }
let(:remote_key) { "this is the encryption key!" }

before { EvmSpecHelper.create_guid_miq_server_zone }

it "removes a key if configured" do
FactoryGirl.create(
:auth_token,
:resource_id => remote_region.id,
:resource_type => "MiqRegion",
:auth_key => remote_key,
:authtype => "system_api"
)
expect(remote_region.auth_key_configured?).to be true
remote_region.remove_auth_key
remote_region.reload
expect(remote_region.auth_key_configured?).to be false
end
end

describe "#api_system_auth_token" do
it "generates the token correctly" do
user = "admin"
server = FactoryGirl.create(:miq_server, :has_active_webservices => true)
expect(region).to receive(:authentication_token).and_return(File.read(Rails.root.join("certs/v2_key")))

token = region.api_system_auth_token(user)
token_hash = YAML.load(MiqPassword.decrypt(token))
Expand All @@ -234,30 +168,6 @@
end
end

describe "#required_credential_fields" do
it "checks the right credential fields" do
expect(region.required_credential_fields(:system_api)).to eq([:auth_key])
end
end

describe "#encrypt" do
let(:region) { FactoryGirl.create(:miq_region, :region => ApplicationRecord.my_region_number) }

it "correctly encrypts a string using the authentication token" do
expect(region).to receive(:authentication_token).and_return(File.read(Rails.root.join("certs/v2_key")))

a_string = "this should be encrypted correctly"
enc = region.encrypt(a_string)
other_string = MiqPassword.decrypt(enc)

expect(other_string).to eq(a_string)
end

it "raises if no key is configured" do
expect { region.encrypt("a string") }.to raise_error(RuntimeError)
end
end

context "ConfigurationManagementMixin" do
describe "#settings_for_resource" do
it "returns the resource's settings" do
Expand Down
49 changes: 18 additions & 31 deletions spec/models/mixins/inter_region_api_method_relay_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,41 +176,28 @@ def expect_api_call(expected_action, expected_args = nil)
expect(MiqRegion).to receive(:find_by).with(:region => region_number).and_return(region)
end

context "with authentication configured" do
before do
expect(region).to receive(:auth_key_configured?).and_return true
end

it "opens an api connection to that address when the server has an ip address" do
require "manageiq-api-client"

server.ipaddress = "192.0.2.1"
server.save!

expect(User).to receive(:current_userid).and_return(request_user)
expect(region).to receive(:api_system_auth_token).with(request_user).and_return(region_auth_token)

client_connection_hash = {
:url => "https://#{server.ipaddress}",
:miqtoken => region_auth_token,
:ssl => {:verify => false}
}
expect(ManageIQ::API::Client).to receive(:new).with(client_connection_hash).and_return(api_connection)
described_class.api_client_connection_for_region(region_number)
end

it "raises if the server doesn't have an ip address" do
expect {
described_class.api_client_connection_for_region(region_number)
}.to raise_error("Failed to establish API connection to region #{region_number}")
end
it "opens an api connection to that address when the server has an ip address" do
require "manageiq-api-client"

server.ipaddress = "192.0.2.1"
server.save!

expect(User).to receive(:current_userid).and_return(request_user)
expect(region).to receive(:api_system_auth_token).with(request_user).and_return(region_auth_token)

client_connection_hash = {
:url => "https://#{server.ipaddress}",
:miqtoken => region_auth_token,
:ssl => {:verify => false}
}
expect(ManageIQ::API::Client).to receive(:new).with(client_connection_hash).and_return(api_connection)
described_class.api_client_connection_for_region(region_number)
end

it "raises without authentication configured" do
expect(region).to receive(:auth_key_configured?).and_return false
it "raises if the server doesn't have an ip address" do
expect {
described_class.api_client_connection_for_region(region_number)
}.to raise_error("Region #{region_number} is not configured for central administration")
}.to raise_error("Failed to establish API connection to region #{region_number}")
end
end

Expand Down
17 changes: 0 additions & 17 deletions spec/models/pglogical_subscription_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -370,23 +370,6 @@ def with_an_invalid_remote_schema

sub.delete
end

it "removes the region authentication key if present" do
allow(pglogical).to receive(:subscriptions).and_return(subscriptions, [subscriptions.last])
expect(pglogical).to receive(:subscription_drop).with("region_#{remote_region1}_subscription", true)

EvmSpecHelper.create_guid_miq_server_zone
auth = FactoryGirl.create(
:auth_token,
:resource_id => remote_region.id,
:resource_type => "MiqRegion",
:auth_key => "this is the encryption key!",
:authtype => "system_api"
)

sub.delete
expect(AuthToken.find_by_id(auth.id)).to be_nil
end
end

describe "#validate" do
Expand Down

0 comments on commit 33c19ae

Please sign in to comment.