How to recursively change the owner and group on a directory with Chef?

倖福魔咒の 提交于 2019-12-05 09:39:10

问题


the resource_directory has only 2 actions available: create and delete

I need to update the owner and group of a directory recursively.

How do I do that?

using a simple resource_execute?

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :run
end

回答1:


You can set the default action to nothing then have resources that may screw things up notify the perm fixer:

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :nothing
end

resource "that may screw up perms" do
  stuff "one two three"
  notifies :run, execute "chown-data-www"
end

with more options you could have the action :run but not if the parent folder is already the correct perms. You could alter this to include a deeper/problem file/directory, or with a find command similar to this

execute "chown-data-www" do
  command "chown -R www-data:www-data /var/www/myfoler"
  user "root"
  action :run
  not_if '[ $(stat -c %U /var/www/myfolder) = "www-data" ]'
end

Edit: fix to reflect comment below




回答2:


We could write a chef resource which iterates through your directory hierarchy and creates a file or directory resource for every file that it finds and then set it up to manage the owner and group on those files. You won't like that, however, since if you have a thousand files in that directory then you'll get a thousand chef resources and your converges will be slow.

If you want to you can, in fact, roll your own code which does something like that which I wrote in the ticket tickets.opscode.com/browse/CHEF-690 which @name referenced, but I wouldn't recommend it.

If you're trying to prevent "tampering" and fix random corruption of user and group attributes then your solution is probably correct. You'll always execute that command on every chef convergence and the resource will always show as being updated, but the command will run as fast as possible (chown -R is basically convergent and idempotent as it checks the perms before trying to set the perms). You will not get reporting back on fixed perms which is the only downside.

If you are just trying to fix the perms once on building a server, then you should throw a not_if conditional in there to check that if the root directory has the correct perms you don't run it every time. That will give you idempotent behavior and will not execute the command on every run, but the downside is clearly that if one of the files under that directory structure has its perms mangled by someone or something in the future, then it will not get corrected.

There's a possible use case here for a single resource which behaves like chown -R and then reports what it fixed (and array of files that had perms changed) which would be useful for cases like SOX and PCI-DSS reporting, but we don't currently cover that use case.

tl;dr is that your solution is fine and you can add a not_if guard if you like




回答3:


If this as a one-off to fix permissions your shortest path might be just knife ssh. (I just did that after ending up here on my own search.)

knife ssh 'name:*' "sudo chown -R $user:$group /full/path/to/directory"

knife ssh 'name:*' "sudo chmod -R 770 /full/path/to/directory"

If I were setting this up from scratch I think I'd need to set up the directory path and proper permissions with one line (NOTE: explicitly apply the perms to each parent in the path)

%w[ /foo /foo/bar /foo/bar/baz ].each do |path|
  directory path do
    owner 'root'
    group 'root'
    mode '0755'
  end

and then create each individual file as a cookbook_file.




回答4:


https://stackoverflow.com/a/28283020/11822923

Answer met my need but there is an issue with grep command, even if the user is apache2 or apach the grep exit code will be 0, but I needed the user to exactly be apache (Apache web server user on CentOS 7.7).

Here is my recipe:

node["apache"]["sites"].each do |sitename, data|
  document_root = "/content/sites/#{sitename}"

  directory document_root do
    action :create
    mode "0755"
    recursive true
    owner "apache"
    group "apache"
  end

  execute "chown_to_apache_user" do
    command "chown -R apache:apache /content"
    user "root"
    action :run
    not_if '[ $(stat -c %U /content/) = "apache" ]'
  end

  template "/etc/httpd/conf.d/#{sitename}.conf" do
    source "vhost.erb"
    mode "0644"
    variables(
      :document_root => document_root,
      :port => data["port"],
      :domain => data["domain"]
    )
    notifies :restart, "service[httpd]"
  end

end

For comparison:

P.S.: to check group as well:

node["apache"]["sites"].each do |sitename, data|
  document_root = "/content/sites/#{sitename}"

  directory document_root do
    action :create
    mode "0755"
    recursive true
    owner "apache"
    group "apache"
  end

  execute "chown_to_apache_user" do
    command "chown -R apache:apache /content"
    user "root"
    action :run
    not_if '[ $(stat -c %U /content/) = "apache" ] && [ $(stat -c %G /content/) = "apache" ]'
  end

  template "/etc/httpd/conf.d/#{sitename}.conf" do
    source "vhost.erb"
    mode "0644"
    variables(
      :document_root => document_root,
      :port => data["port"],
      :domain => data["domain"]
    )
    notifies :restart, "service[httpd]"
  end

end



回答5:


I would use plain resource directory with action :create. Per documentation:

:create
Default. Create a directory. If a directory already exists (but does not match), update that directory to match

https://docs.chef.io/resource_directory.html



来源:https://stackoverflow.com/questions/23921708/how-to-recursively-change-the-owner-and-group-on-a-directory-with-chef

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!