homebrew icon indicating copy to clipboard operation
homebrew copied to clipboard

Homebrew need sudoers right without password when using chef as service

Open ygini opened this issue 7 years ago • 8 comments

Cookbook version

2.1.0

Chef-client version

12.12.15

Platform Details

OS X 10.11.6 with chef-client run as service (created by chef-client resource)

Scenario:

When deploying system, a kickstart script install chef and register workstation to my chef server and run content from a default role.

No one is connected and the workstation is made for multiple non admin user.

A default admin user is installed and set as target user for homebrew via node attributes.

Expected Result:

Homebrew should be able installed and scenario should continue.

Actual Result:

Homebrew install fail due to design errors in the way homebrew work (it's not your fault, homebrew is a PITA in term of system management, nothing is done properly).

Here is the error:

Expected process to exit with [0], but received '1'
---- Begin output of /var/chef/cache/homebrew_go ----
STDOUT: ==> This script will install:
/usr/local/bin/brew
/usr/local/Library/...
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
==> /usr/bin/sudo /bin/mkdir -p /Users/macadmin/Library/Caches/Homebrew
STDERR: sudo: no tty present and no askpass program specified
Failed during: /usr/bin/sudo /bin/mkdir -p /Users/macadmin/Library/Caches/Homebrew
---- End output of /var/chef/cache/homebrew_go ----
Ran /var/chef/cache/homebrew_go returned 1

Indeed, homebrew install script make a heavy use of sudo command. But they never thinked about mass deployment scenario where sudo isn't available…

To make this work you've to add a file with the following content to /etc/sudoers.d

<homebrew owner>        ALL=(ALL) NOPASSWD: ALL

And then, it work…

It might be interesting to package this hack into the homebrew installer recipe…

(of course, create this file only if needed and delete it as soon as possible)

ygini avatar Aug 04 '16 14:08 ygini

When you try to execute /var/chef/cache/homebrew_go you get this:

/var/chef/cache/homebrew_go
==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew
==> The following existing directories will be made group writable:
/usr/local/bin
==> The following existing directories will have their owner set to roblox:
/usr/local/bin
==> The following existing directories will have their group set to admin:
/usr/local/bin
==> The following new directories will be created:
/usr/local/Cellar
/usr/local/Homebrew
/usr/local/Frameworks
/usr/local/etc
/usr/local/include
/usr/local/lib
/usr/local/opt
/usr/local/sbin
/usr/local/share
/usr/local/share/zsh
/usr/local/share/zsh/site-functions
/usr/local/var

Press RETURN to continue or any other key to abort

When you press RETURN you get a prompt for the admin password.

Press RETURN to continue or any other key to abort
==> /usr/bin/sudo /bin/chmod g+rwx /usr/local/bin
Password:

Sauraus avatar Oct 04 '16 18:10 Sauraus

Actually you can make this much more restrictive by doing this

#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /bin/chmod
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /usr/sbin/chown
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /bin/mkdir
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /usr/bin/chgrp
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /usr/bin/touch
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /usr/sbin/softwareupdate
#{homebrew_owner} #{node['hostname']}=(root) NOPASSWD: /bin/rm

that way at least you expose the bare minimum required permissions.

user = homebrew_owner host = node['hostname']

Sauraus avatar Oct 04 '16 20:10 Sauraus

However this does not resolve the initial

Press RETURN to continue or any other key to abort

problem this is something entirely different.

Here is another thing I observed, when I run kitchen converge I do not get the prompt, however running the command on an physical node does create this prompt. The easiest workaround for the Press RETURN prompt is to add </dev/null to the execution which will suppress tty and thus the prompt.

Sauraus avatar Oct 04 '16 20:10 Sauraus

Here is the code in homebrew_go:

def wait_for_user
  puts
  puts "Press RETURN to continue or any other key to abort"
  c = getc
  # we test for \r and \n because some stuff does \r instead
  abort unless c == 13 or c == 10
end

Which is called right after listing all directories that will be created...

wait_for_user if STDIN.tty? && !ENV["TRAVIS"]

Sauraus avatar Oct 04 '16 20:10 Sauraus

Indeed, you can filter your sudo rights to be more restrictive, but that mean heavy testing on each new homebrew version to discover new wonderful idea they got…

Homebrew is poorly designed so trying to do things correctly when packaging homebrew might not be a really simple task.

For example, how does it play with last version of homebrew who finally do things correctly due to SIP restrictions in 10.12? (i.e.: don't put a mess in /usr/local but clean your room and stay in /usr/local/homebew)

ygini avatar Oct 05 '16 05:10 ygini

I actually tested this on 10.12 and 10.11 both behave in the same way and the brew install is still messed up. :(

I will however move the actual commands that we need sudo access to during the install into an attribute such that these can be fine tuned when brew install changes things.

Sauraus avatar Oct 05 '16 15:10 Sauraus

PR updated. :)

Sauraus avatar Oct 05 '16 15:10 Sauraus

Is there any other updates on this or the pull request? :) I'd really like to see this or another fix go in soon. This has been a big issue in our environment.

kameghamegha avatar Nov 07 '16 18:11 kameghamegha