Skip to content

Commit

Permalink
Merge pull request #190 from chef-cookbooks/boot_start_execute_umask
Browse files Browse the repository at this point in the history
sets umask when executing the `execute[splunk enable boot-start]`
  • Loading branch information
haidangwa authored Oct 24, 2020
2 parents b85f319 + 9abae86 commit e4ea873
Show file tree
Hide file tree
Showing 26 changed files with 218 additions and 114 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ jobs:
- name: Run yaml Lint
uses: actionshub/yamllint@master

dokken:
vagrant:
needs: [yamllint, delivery]
runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
matrix:
os:
Expand All @@ -55,17 +55,17 @@ jobs:
uses: actions/checkout@master
- name: Install Chef
uses: actionshub/chef-install@master
- name: Dokken
uses: actionshub/kitchen-dokken@master
- name: Test Kitchen
uses: actionshub/test-kitchen@master
env:
CHEF_LICENSE: accept-no-persist
KITCHEN_LOCAL_YAML: test/kitchen/kitchen.dokken.yml
KITCHEN_LOCAL_YAML: test/kitchen/kitchen.vagrant.yml
with:
suite: ${{ matrix.suite }}
os: ${{ matrix.os }}

final:
needs: [dokken]
needs: [vagrant]
runs-on: ubuntu-latest
steps:
- name: Check out code
Expand Down
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ lib/bundler/man
pkg
test/tmp
test/version_tmp
test/kitchen/kitchen.ec2.yml
test/kitchen/user-data.sh
tmp
_Store
*~
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

This file is used to list changes made in each version of the splunk cookbook.

## 7.0.0 (2020-10-22)
**BREAKING CHANGE**
- sets umask when executing the `execute[splunk enable boot-start]` resource
- adds new attribute, `default['splunk']['enable_boot_start_umask']` for umask setting applied to `execute[splunk enable boot-start]` (Default: '18')
- `#splunk_cmd` now requires a dynamic array of arguments that will be appended to the splunk command
- `splunk.service` is symlinked to the systemd unit
- adds a kitchen-vagrant config to run inside Github Actions
- enhancements to the `:remove` action for `splunk_installer` resource to ensure a complete uninstall for both Splunk Enterprise Server and Universal Forwarder

## 6.4.1 (2020-10-20)
- Fixes an issue running Splunk and the Splunk Universal Forwarder as a non-root user
- Fixes Test Kitchen configuration to test running Splunk as non-root user
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,30 @@ must be set explicitly elsewhere on the node(s).
node.force_default['splunk']['server']['upgrade']['url'] = nil
```

## Helper methods
### splunk_cmd
When wrapping this cookbook, it is often beneficial to run Splunk Enterprise or Universal Forwarder as a non-root user. This is, in fact, a security recommendation to run Splunk as a non-root user. To this end, `#splunk_cmd` will return the properly constructed command to run a Splunk CLI command with arguments.

Example:
```
execute 'set servername' do
command splunk_cmd(['set', 'servername', node.name, '-auth', node.run_state['splunk_auth_info'])
sensitive true
notifies :restart, 'service[splunk]'
end
```

another way that will result in the same command:

```
execute 'set servername' do
command splunk_cmd("set servname #{node.name} -auth '#{node.run_state['splunk_auth_info']}'")
sensitive true
notifies :restart, 'service[splunk]'
end
```


## Custom Resources

### splunk_app
Expand Down
1 change: 1 addition & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
default['splunk']['ratelimit_kilobytessec'] = '2048'
default['splunk']['disabled'] = false
default['splunk']['data_bag'] = 'vault'
default['splunk']['enable_boot_start_umask'] = '18'

default['splunk']['setup_auth'] = true
default['splunk']['service_name'] = 'splunk' # Splunk changes this to Splunkd or SplunkForwarder on systemd-managed servers
Expand Down
4 changes: 2 additions & 2 deletions kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ suites:
clustering:
enabled: true
mode: master
replication_factor: 5
search_factor: 3
replication_factor: 2
search_factor: 1
verifier:
name: inspec
inspec_tests:
Expand Down
36 changes: 18 additions & 18 deletions libraries/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@ module Helpers
def boot_start_cmd(disable = nil)
systemd_managed = systemd? ? 1 : 0

# this command modifies the systemd unit file, so must be run as root
if disable.nil? && run_as_root?
"#{splunk_cmd} enable boot-start -systemd-managed #{systemd_managed} --accept-license"
"#{splunk_dir}/bin/splunk enable boot-start -systemd-managed #{systemd_managed} --accept-license"
elsif disable.nil?
"#{splunk_cmd} enable boot-start -user #{splunk_runas_user} -systemd-managed #{systemd_managed} --accept-license"
"#{splunk_dir}/bin/splunk enable boot-start -user #{splunk_runas_user} -systemd-managed #{systemd_managed} --accept-license"
else
"#{splunk_cmd} disable boot-start -systemd-managed #{systemd_managed} --accept-license"
"#{splunk_dir}/bin/splunk disable boot-start -systemd-managed #{systemd_managed} --accept-license"
end
end

# returns the output of splunk's HASHED_PASSWORD command
# this command produces a hash of a clear-text password that can be stored in user-seed.conf, for example
def hash_passwd(pw)
return pw if pw.match?(/^\$\d*\$/)
hash = shell_out("#{splunk_cmd} hash-passwd #{pw}")
hash = shell_out("#{splunk_dir}/bin/splunk hash-passwd #{pw}")
hash.stdout.strip
end

Expand All @@ -51,7 +52,7 @@ def license_accepted?
end

def splunk_installed?
::File.exist?(splunk_cmd)
::File.exist?("#{splunk_dir}/bin/splunk")
end

def splunk_file(uri)
Expand All @@ -60,8 +61,11 @@ def splunk_file(uri)
Pathname.new(URI.parse(uri).path).basename.to_s
end

def splunk_cmd
"#{splunk_dir}/bin/splunk"
def splunk_cmd(*args)
cmd = "#{splunk_dir}/bin/splunk #{args.join(' ')}"

return cmd if splunk_runas_user == 'root'
"su - #{splunk_runas_user} -c '#{cmd}'"
end

# a way to return the right command to stop, start, and restart the splunk
Expand All @@ -73,10 +77,7 @@ def svc_command(action = 'start')
raise "Failed to #{action}"
end

command = "#{splunk_cmd} #{action} --answer-yes --no-prompt --accept-license"

return command if splunk_runas_user == 'root'
"su - #{splunk_runas_user} -c '#{command}'"
splunk_cmd("#{action} --answer-yes --no-prompt --accept-license")
end

def splunk_dir
Expand Down Expand Up @@ -109,7 +110,7 @@ def splunk_auth(auth)

def splunk_login_successful?
return false unless splunk_installed?
login = shell_out("#{splunk_cmd} login -auth #{node.run_state['splunk_auth_info']}")
login = shell_out(splunk_cmd(%w(login -auth node.run_state['splunk_auth_info'])))
login.stderr.strip.empty? && login.stdout.strip.empty? && login.exitstatus == 0
end

Expand Down Expand Up @@ -148,7 +149,7 @@ def port_open?(port, ip = '127.0.0.1')
end

def current_mgmt_port
splunk = shell_out("#{splunk_cmd} show splunkd-port -auth #{node.run_state['splunk_auth_info']} | awk -F: '{print$NF}'")
splunk = shell_out(splunk_cmd("show splunkd-port -auth #{node.run_state['splunk_auth_info']} | awk -F: '{print$NF}'"))
splunk.error! # Raise an exception if it didn't exit with 0
splunk.stdout.strip
end
Expand Down Expand Up @@ -190,7 +191,7 @@ def cluster_master?

def init_shcluster_member?
return false unless splunk_installed?
list_member_info = shell_out("#{splunk_cmd} list shcluster-member-info -auth #{node.run_state['splunk_auth_info']}")
list_member_info = shell_out(splunk_cmd("list shcluster-member-info -auth #{node.run_state['splunk_auth_info']}"))
list_member_info.error?
end

Expand Down Expand Up @@ -224,7 +225,7 @@ def shcluster_servers_size
end

def shcluster_members_ipv4
splunk = shell_out("#{splunk_cmd} list shcluster-members -auth #{node.run_state['splunk_auth_info']} | grep host_port_pair | awk -F: '{print$2}'")
splunk = shell_out(splunk_cmd("list shcluster-members -auth #{node.run_state['splunk_auth_info']} | grep host_port_pair | awk -F: '{print$2}'"))
return [] if splunk.stdout.strip == 'Encountered some errors while trying to obtain shcluster status.'
splunk.stdout.split
end
Expand All @@ -240,8 +241,7 @@ def shcaptain_elected?
def shcluster_captain
return unless splunk_installed?

command = "#{splunk_cmd} show shcluster-status -auth '#{node.run_state['splunk_auth_info']}' | " \
'grep -A 5 Captain | tail -1'
command = splunk_cmd("show shcluster-status -auth '#{node.run_state['splunk_auth_info']}' | grep -A 5 Captain | tail -1'")
shcluster_captain = shell_out(command)
stdout = shcluster_captain.stdout.strip
return unless stdout.match(/^label \: .*/)
Expand All @@ -260,7 +260,7 @@ def ok_to_add_member?

def search_heads_peered?
return false unless splunk_installed?
list_search_server = shell_out("#{splunk_cmd} list search-server -auth #{node.run_state['splunk_auth_info']}")
list_search_server = shell_out(splunk_cmd("list search-server -auth #{node.run_state['splunk_auth_info']}"))
list_search_server.stdout.match?(/(^Server at URI \".*\" with status as \"Up\")+/)
end

Expand Down
2 changes: 1 addition & 1 deletion metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
maintainer_email '[email protected]'
license 'Apache-2.0'
description 'Manage Splunk Enterprise or Splunk Universal Forwarder'
version '6.4.1'
version '7.0.0'

supports 'debian', '>= 8.9'
supports 'ubuntu', '>= 16.04'
Expand Down
3 changes: 2 additions & 1 deletion recipes/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
# if the splunk daemon is running as root, executing a normal service restart or stop will fail if the boot
# start script has been modified to execute splunk as a non-root user.
# So, the splunk daemon must be run this way instead
execute "#{splunk_cmd} stop" do
execute 'splunk stop' do
command splunk_cmd('stop')
action :nothing
not_if { node['splunk']['server']['runasroot'] == true }
end
Expand Down
4 changes: 2 additions & 2 deletions recipes/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
include_recipe 'chef-splunk::setup_auth' if setup_auth?

execute 'update-splunk-mgmt-port' do
command "#{splunk_cmd} set splunkd-port #{node['splunk']['mgmt_port']} -auth '#{node.run_state['splunk_auth_info']}'"
command splunk_cmd("set splunkd-port #{node['splunk']['mgmt_port']} -auth '#{node.run_state['splunk_auth_info']}'")
sensitive true unless Chef::Log.debug?
not_if { current_mgmt_port == node['splunk']['mgmt_port'] }
notifies :restart, 'service[splunk]' unless disabled?
Expand All @@ -33,7 +33,7 @@
ruby_block 'enable-splunk-receiver-port' do
sensitive true unless Chef::Log.debug?
block do
splunk = Mixlib::ShellOut.new("#{splunk_cmd} enable listen #{node['splunk']['receiver_port']} -auth #{node.run_state['splunk_auth_info']}")
splunk = Mixlib::ShellOut.new(splunk_cmd("enable listen #{node['splunk']['receiver_port']} -auth #{node.run_state['splunk_auth_info']}"))
splunk.run_command
true if splunk.stderr.include?("Configuration for port #{node['splunk']['receiver_port']} already exists")
end
Expand Down
19 changes: 14 additions & 5 deletions recipes/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
# if the splunk daemon is running as root, executing a normal service restart or stop will fail if the boot
# start script has been modified to execute splunk as a non-root user.
# So, the splunk daemon must be run this way instead
execute "#{splunk_cmd} stop" do
execute 'splunk stop' do
command splunk_cmd('stop')
action :nothing
subscribes :run, 'execute[splunk enable boot-start]', :before
end
Expand All @@ -76,11 +77,16 @@
only_if { systemd? }
end

execute 'splunk enable boot-start' do
command boot_start_cmd
execute "splunk #{disabled? ? 'disable' : 'enable'} boot-start" do
command boot_start_cmd(disabled? ? true : nil)
sensitive false
retries 3
creates node['splunk']['startup_script']
umask node['splunk']['enable_boot_start_umask']
end

link '/etc/systemd/system/splunk.service' do
to server? ? '/etc/systemd/system/Splunkd.service' : '/etc/systemd/system/SplunkForwarder.service'
end

default_service_action = if node['splunk']['disabled'] == true
Expand All @@ -95,8 +101,11 @@
service_name node['splunk']['service_name']
action default_service_action
supports status: true, restart: true
status_command "#{splunk_dir}/bin/splunk status"
status_command svc_command('status')
timeout 1800
provider splunk_service_provider
subscribes :restart, 'template[user-seed.conf]', :immediately unless disabled?
unless disabled?
subscribes :restart, 'template[user-seed.conf]', :immediately
subscribes :restart, "user[#{node['splunk']['user']['username']}]", :immediately
end
end
2 changes: 1 addition & 1 deletion recipes/setup_auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
_user, pw = node.run_state['splunk_auth_info'].split(':')

file '.user-seed.conf' do
action :nothing
action splunk_login_successful? ? :nothing : :delete
path "#{splunk_dir}/etc/system/local/.user-seed.conf"
subscribes :touch, 'file[user-seed.conf]', :immediately
end
Expand Down
19 changes: 11 additions & 8 deletions recipes/setup_clustering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,20 @@

splunk_cmd_params << " -secret #{node.run_state['splunk_secret']}" if node.run_state['splunk_secret']

file "#{splunk_dir}/etc/.setup_clustering" do
action :nothing
owner splunk_runas_user
group splunk_runas_user
mode '600'
subscribes :touch, 'execute[setup-indexer-cluster]'
end

execute 'setup-indexer-cluster' do
command "#{splunk_cmd} edit cluster-config #{splunk_cmd_params} -auth '#{node.run_state['splunk_auth_info']}'"
command splunk_cmd("edit cluster-config #{splunk_cmd_params} -auth '#{node.run_state['splunk_auth_info']}'")
sensitive true unless Chef::Log.debug?
retries 5
retry_delay 60
not_if { ::File.exist?("#{splunk_dir}/etc/.setup_clustering") }
notifies :start, 'service[splunk]', :before unless disabled?
notifies :restart, 'service[splunk]' unless disabled?
end

file "#{splunk_dir}/etc/.setup_clustering" do
content "true\n"
owner splunk_runas_user
group splunk_runas_user
mode '600'
end
13 changes: 6 additions & 7 deletions recipes/setup_shclustering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@
# this effectively waits until the captain is ready before adding members to the cluster
execute 'initialize search head cluster member' do
sensitive true unless Chef::Log.debug?
command "#{splunk_cmd} init shcluster-config -auth '#{node.run_state['splunk_auth_info']}' " \
command splunk_cmd("init shcluster-config -auth '#{node.run_state['splunk_auth_info']}' " \
"-mgmt_uri #{node['splunk']['shclustering']['mgmt_uri']} " \
"-replication_port #{node['splunk']['shclustering']['replication_port']} " \
"-replication_factor #{node['splunk']['shclustering']['replication_factor']} " \
"-conf_deploy_fetch_url #{node['splunk']['shclustering']['deployer_url']} " \
"-secret #{node.run_state['splunk_secret']} " \
"-shcluster_label #{node['splunk']['shclustering']['label']}"
"-shcluster_label #{node['splunk']['shclustering']['label']}")
notifies :restart, 'service[splunk]', :immediately unless disabled?
only_if { init_shcluster_member? }
end
Expand All @@ -120,16 +120,15 @@
if ok_to_bootstrap_captain?
execute 'bootstrap-shcluster-captain' do
sensitive true unless Chef::Log.debug?
command "#{splunk_cmd} bootstrap shcluster-captain -auth '#{node.run_state['splunk_auth_info']}' " \
"-servers_list \"#{shcluster_servers_list.join(',')}\""
command splunk_cmd("bootstrap shcluster-captain -auth '#{node.run_state['splunk_auth_info']}' -servers_list \"#{shcluster_servers_list.join(',')}\"")
notifies :restart, 'service[splunk]', :immediately unless disabled?
end
elsif ok_to_add_member?
captain_mgmt_uri = "https://#{shcluster_captain}:8089"

execute 'add member to search head cluster' do
sensitive true unless Chef::Log.debug?
command "#{splunk_cmd} add shcluster-member -current_member_uri #{captain_mgmt_uri} -auth '#{node.run_state['splunk_auth_info']}'"
command splunk_cmd("add shcluster-member -current_member_uri #{captain_mgmt_uri} -auth '#{node.run_state['splunk_auth_info']}'")
notifies :restart, 'service[splunk]' unless disabled?
end
end
Expand All @@ -152,8 +151,8 @@
cluster_master['num_sites'] = result['cluster_num_sites']
end

shpeer_integration_command = "#{splunk_cmd} edit cluster-config -mode searchhead -master_uri #{cluster_master['mgmt_uri']} " \
"-secret #{node.run_state['splunk_secret']} -auth #{node.run_state['splunk_auth_info']}"
shpeer_integration_command = splunk_cmd("edit cluster-config -mode searchhead -master_uri #{cluster_master['mgmt_uri']} " \
"-secret #{node.run_state['splunk_secret']} -auth #{node.run_state['splunk_auth_info']}")
shpeer_integration_command += ' -site site0' if cluster_master['num_sites'] > 1

execute 'search head cluster integration with indexer cluster' do
Expand Down
Loading

0 comments on commit e4ea873

Please sign in to comment.