itchef/cookbooks/cpe_helpers/spec/console_user_spec.rb (231 lines of code) (raw):

# Copyright (c) Facebook, Inc. and its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chefspec' require_relative '../libraries/cpe_helpers' require_relative '../../cpe_logger/libraries/cpe_log' describe CPE::Helpers do context 'When on Linux' do before do allow(CPE::Helpers).to receive(:macos?).and_return(false) allow(CPE::Helpers).to receive(:linux?).and_return(true) allow(CPE::Helpers).to receive(:windows?).and_return(false) allow(CPE::Log).to receive(:log) allow(CPE::Helpers).to receive(:machine_owner). and_return('from_machine_owner') allow(::File).to receive(:exist?).with('/usr/bin/loginctl'). and_return(true) allow(::File).to receive(:exist?).with('/bin/loginctl'). and_return(false) end context 'When loginctl does not exist' do before do CPE::Helpers.instance_variable_set :@console_user, nil CPE::Helpers.instance_variable_set :@loginctl_users, nil allow(::File).to receive(:exist?).with('/usr/bin/loginctl'). and_return(false) end it 'console_user returns machine owner' do expect(CPE::Helpers.console_user).to eq('from_machine_owner') end end context 'When loginctl returns no end-user' do context 'When shell_out fails' do before do CPE::Helpers.instance_variable_set :@console_user, nil CPE::Helpers.instance_variable_set :@loginctl_users, nil allow(CPE::Helpers).to receive(:shell_out). with('/usr/bin/loginctl --no-legend list-users').and_return( double( :error? => true, ), ) end it 'loginctl_users should return []' do expect(CPE::Helpers.loginctl_users).to eq([]) end it 'console_user should return machine owner' do expect(CPE::Helpers.console_user).to eq('from_machine_owner') end end context 'When shell_out returns only gdm' do before do CPE::Helpers.instance_variable_set :@console_user, nil CPE::Helpers.instance_variable_set :@loginctl_users, nil allow(CPE::Helpers).to receive(:shell_out). with('/usr/bin/loginctl --no-legend list-users').and_return( double( :error? => false, :stdout => " 42 gdm \n", ), ) end it 'loginctl_users should return a list with gdm' do expect(CPE::Helpers.loginctl_users).to eq( [{ 'uid' => 42, 'user' => 'gdm' }], ) end it 'console_user should return machine owner' do expect(CPE::Helpers.console_user).to eq('from_machine_owner') end end context 'When shell_out returns only an end user' do before do CPE::Helpers.instance_variable_set :@console_user, nil CPE::Helpers.instance_variable_set :@loginctl_users, nil allow(CPE::Helpers).to receive(:shell_out). with('/usr/bin/loginctl --no-legend list-users').and_return( double( :error? => false, :stdout => "1001 endusr\n", ), ) end it 'loginctl_users should return a list with endusr' do expect(CPE::Helpers.loginctl_users).to eq( [{ 'uid' => 1001, 'user' => 'endusr' }], ) end it 'console_user should return endusr' do expect(CPE::Helpers.console_user).to eq('endusr') end end context 'When shell_out returns gdm and an end user' do before do CPE::Helpers.instance_variable_set :@console_user, nil CPE::Helpers.instance_variable_set :@loginctl_users, nil allow(CPE::Helpers).to receive(:shell_out). with('/usr/bin/loginctl --no-legend list-users').and_return( double( :error? => false, :stdout => " 1001 endusr \n" + " 42 gdm \n", ), ) end it 'loginctl_users should return a list with gdm and endusr' do require 'set' expect(CPE::Helpers.loginctl_users.to_set).to eq( [{ 'uid' => 42, 'user' => 'gdm' }, { 'uid' => 1001, 'user' => 'endusr' }].to_set, ) end it 'console_user should return endusr' do expect(CPE::Helpers.console_user).to eq('endusr') end end end end context 'When on Windows' do context '#logged_on_user_query' do subject { CPE::Helpers } NO_USER = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME EOF ONE_USER = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME >testdummy console 1 Active none 8/31/2020 12:22 PM EOF TWO_USERS = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME testdummy console 1 Active none 8/31/2020 12:22 PM testdummy2 console 1 Active none 8/31/2020 18:00 PM EOF INACTIVE_USERS = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME testdummy console 1 Inactive none 8/31/2020 12:22 PM testdummy2 console 1 Active none 8/31/2020 18:00 PM EOF MISSING_FIELD = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME testdummy console 1 EOF NO_ACTIVE_USERS = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME testdummy console 1 Inactive none 8/31/2020 12:22 PM testdummy2 console 1 Inactive none 8/31/2020 18:00 PM EOF OUTPUT_DIFFERENT_LANG = <<-'EOF'.freeze USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME >testdummy console 1 Actif aucun 8/31/2020 12:22 PM EOF before do allow(Chef::Log).to receive(:debug) end it 'should return nil if there is an exception' do allow(subject).to receive(:shell_out).and_raise(NoMethodError, 'aieee') expect(subject.logged_on_user_query).to be nil end it 'should return nil if the command output is empty' do result = double(:stdout => '') allow(subject).to receive(:shell_out).and_return(result) expect(subject.logged_on_user_query).to be nil end it 'should return nil if the output does not contain a user' do result = double(:stdout => NO_USER) allow(subject).to receive(:shell_out).and_return(result) expect(subject.logged_on_user_query).to be nil end it 'should return nil if the command times out' do allow(subject).to receive(:shell_out).and_raise( Mixlib::ShellOut::CommandTimeout, ) allow(Chef::Log).to receive(:warn) expect(Chef::Log).to receive(:warn). with('command timeout while looking up user'). once expect(subject.logged_on_user_query).to be nil end { 'should return nil if a field is missing for whatever reason' => { 'output' => MISSING_FIELD }, 'should return nil if no active users' => { 'output' => NO_ACTIVE_USERS }, 'should return nil when output is in different language' => { 'output' => OUTPUT_DIFFERENT_LANG }, }.each do |test_name, test_data| it test_name do result = double(:stdout => test_data['output']) allow(subject).to receive(:shell_out).and_return(result) expect(subject.logged_on_user_query).to be nil end end { 'should return testdummy' => { 'output' => ONE_USER, 'expected' => 'testdummy' }, 'should return testdummy when two users are present' => { 'output' => TWO_USERS, 'expected' => 'testdummy' }, 'should return testdummy2 when testdummy is inactive' => { 'output' => INACTIVE_USERS, 'expected' => 'testdummy2' }, }.each do |test_name, test_data| it test_name do result = double(:stdout => test_data['output']) allow(subject).to receive(:shell_out).and_return(result) expect(subject.logged_on_user_query).to eql test_data['expected'] end end it 'last_logged_on_user_from_registry should return nil if the output does not contain LastLoggedOnUser' do allow(subject).to receive(:logged_on_user_registry).and_return({}) expect(subject.last_logged_on_user_from_registry).to be nil end it 'last_logged_on_user_from_registry should return nil if there is an exception ' do allow(subject).to receive(:logged_on_user_registry).and_raise( NoMethodError, 'blah' ) expect(subject.last_logged_on_user_from_registry).to be nil end logged_on_user_registry_output = { 'LastLoggedOnSAMUser'=>'THEFACEBOOK\\testdummy', 'LastLoggedOnUser'=>'THEFACEBOOK\\testdummy', 'LastLoggedOnUserSID'=>'S-1-5-21-4286658467', 'SelectedUserSID'=>'S-1-5-21-4286658467', } it 'last_logged_on_user_from_registry should parse a valid user ' do allow(subject).to receive(:logged_on_user_registry).and_return( logged_on_user_registry_output, ) expect(subject.last_logged_on_user_from_registry).to eql 'testdummy' end end end end