Dynamically modifying files from a package Chef just installed


#1

Executive Summary:
I’m using Chef to install a package and then update (ownership, permissions)
many of the files installed with the package. Because the files don’t exist
before the package is installed in the execution phase, resources for those
files can’t be dynamically generated in the compile phase. What is the most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle (Mule
ESB). In keeping with what we understand to be the best practices, we have a
library cookbook that simply does the bare-bones install and a policy cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership and
permissions on many of the files that get installed by the library cookbook to
make our security guys happy. My first cut at the default recipe in the policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM, Chef
attempts to create the config file resources during the compile phase but since
Mule doesn’t actually get installed until the execution phase, there are no
config files for which to generate resources. It’s not a huge deal with the
config files since there are only 3 of them, but it’s a bigger problem when we
start getting into the /lib directory, which contains dozens of .jar files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#2

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for those
files can’t be dynamically generated in the compile phase. What is the
most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle
(Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in the
policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM, Chef
attempts to create the config file resources during the compile phase but
since
Mule doesn’t actually get installed until the execution phase, there are no
config files for which to generate resources. It’s not a huge deal with
the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar files
and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#3

Andrew,

First, thanks for the quick response. It’s always a bit nerve-wracking
submitting your first question to a new mailing list.

It seems like if I go down that road, I’ll end up having to explicitly
define a file or directory resource for everything in the package, which
would leave me with a huge policy cookbook that may need a major overhaul
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply
writing a Ruby block that walks the tree of subdirectories and files at
execution time changing ownership and permission seems less “correct” than
using file and directory resources.

Chef isn’t psychic, so I have to believe that my attempt to dynamically
create file and directory resources during the compile phase for stuff that
won’t exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I’m just going to have to write
some execution phase code to walk through the file system and make the
necessary ownership and permission changes on the installed files and
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross andrew@yipit.com wrote:

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for
those
files can’t be dynamically generated in the compile phase. What is the
most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle
(Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership
and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in the
policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM,
Chef
attempts to create the config file resources during the compile phase but
since
Mule doesn’t actually get installed until the execution phase, there are
no
config files for which to generate resources. It’s not a huge deal with
the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar
files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#4

Some additional options instead of using file, just change the
notification.

execute “Set Permissions” do
command “chmod -R 644 /etc/foo/bar
action :nothing
only_if { ::File.exists?(”/etc/foo/bar/baz.conf")}
end

We can also outsource the directory spidering to Ruby (
http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby
)

Set files

Dir.glob("/etc/foo/**/*").each do |f|
file “Set permissions for #{f}” do
mode 00644
action :create
end if ::File.exists?("/etc/foo")

Set Directories

Dir.glob("/etc/foo/**/*/").each do |d|
directory “Set permissions for #{d}” do
mode 00755
action :create
end if ::File.exists?("/etc/foo")

On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Andrew,

First, thanks for the quick response. It’s always a bit nerve-wracking
submitting your first question to a new mailing list.

It seems like if I go down that road, I’ll end up having to explicitly
define a file or directory resource for everything in the package, which
would leave me with a huge policy cookbook that may need a major overhaul
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply
writing a Ruby block that walks the tree of subdirectories and files at
execution time changing ownership and permission seems less “correct” than
using file and directory resources.

Chef isn’t psychic, so I have to believe that my attempt to dynamically
create file and directory resources during the compile phase for stuff that
won’t exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I’m just going to have to
write some execution phase code to walk through the file system and make
the necessary ownership and permission changes on the installed files and
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross andrew@yipit.com wrote:

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for
those
files can’t be dynamically generated in the compile phase. What is the
most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle
(Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership
and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in the
policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM,
Chef
attempts to create the config file resources during the compile phase
but since
Mule doesn’t actually get installed until the execution phase, there are
no
config files for which to generate resources. It’s not a huge deal with
the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar
files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#5

So here’s where I’ve landed. I am using ruby blocks which spider the
directories and create new chef resource objects. I’ve been testing it and
it seems to be working pretty well. Since I’m relying on Chef resources -
even though they’re dynamically generated during the execution phase - the
cookbook is idempotent and Chef isn’t executing any unnecessary actions.

The code looks something like this:

Begin Policy Cookbook Snippet

Cookbook: mule-policy

Recipe: default

Set up a RunContext for later use

@events = Chef::EventDispatch::Dispatcher.new()
run_context = Chef::RunContext.new( node, {}, @events )

Run the library cookbook

include_recipe “mule”

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

ruby_block “restrict_config_files” do
notifies :restart, "service[mule]"
action :create
block do
Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
conf_file = Chef::Resource::File.new( path, run_context )
conf_file.owner node[:mule][:user]
conf_file.group node[:mule][:group]
conf_file.mode "0640"
conf_file.run_action :create
end
end
end

Restrict access to library files

This was the gnarly bit due to the number of .jar files

ruby_block “restrict_library_files” do
notifies :restart, "service[mule]"
action :create
block do
Dir[ “#{node[:mule][:home]}/lib/**/*” ].each do |path|
if File.file?( path )
lib_file = Chef::Resource::File.new( path, run_context )
lib_file.owner node[:mule][:user]
lib_file.group node[:mule][:group]
lib_file.mode "0640"
lib_file.run_action :create
elsif File.directory?( path )
lib_dir= Chef::Resource::Directory.new( path, run_context )
lib_dir.owner node[:mule][:user]
lib_dir.group node[:mule][:group]
lib_dir.mode "0750"
lib_dir.run_action :create
end
end
end
end

End Policy Cookbook Snippet

I’m pretty happy with it. If anyone has any further comments or
suggestions, I’d be glad to hear them.

Thanks,

-Rob

On Fri, Oct 11, 2013 at 12:25 PM, Andrew Gross andrew@yipit.com wrote:

Some additional options instead of using file, just change the
notification.

execute “Set Permissions” do
command “chmod -R 644 /etc/foo/bar
action :nothing
only_if { ::File.exists?(”/etc/foo/bar/baz.conf")}
end

We can also outsource the directory spidering to Ruby (
http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby
)

Set files

Dir.glob("/etc/foo/**/*").each do |f|
file “Set permissions for #{f}” do
mode 00644
action :create
end if ::File.exists?("/etc/foo")

Set Directories

Dir.glob("/etc/foo/**/*/").each do |d|
directory “Set permissions for #{d}” do
mode 00755
action :create
end if ::File.exists?("/etc/foo")

On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Andrew,

First, thanks for the quick response. It’s always a bit nerve-wracking
submitting your first question to a new mailing list.

It seems like if I go down that road, I’ll end up having to explicitly
define a file or directory resource for everything in the package, which
would leave me with a huge policy cookbook that may need a major overhaul
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply
writing a Ruby block that walks the tree of subdirectories and files at
execution time changing ownership and permission seems less “correct” than
using file and directory resources.

Chef isn’t psychic, so I have to believe that my attempt to dynamically
create file and directory resources during the compile phase for stuff that
won’t exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I’m just going to have to
write some execution phase code to walk through the file system and make
the necessary ownership and permission changes on the installed files and
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross andrew@yipit.com wrote:

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for
those
files can’t be dynamically generated in the compile phase. What is the
most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle
(Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership
and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in
the policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM,
Chef
attempts to create the config file resources during the compile phase
but since
Mule doesn’t actually get installed until the execution phase, there
are no
config files for which to generate resources. It’s not a huge deal
with the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar
files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#6

The difference between your excerpt and Rob’s is that his is wrapped in a
ruby_block resource. Your code will be evaluated (and, therefore, the
directory will be walked) during the compile phase … for Rob’s particular
scenario, he wants the directory walk (and resource creation) to take place
after the package is present.

So if he did things your way, it would take two Chef runs to obtain the
desired end state.

I have the feeling everyone on this thread already knew this, but I thought
I’d clarify this for the sake of posterity (i.e. whoever finds this example
via search engine).

On Fri, Oct 11, 2013 at 10:25 AM, Andrew Gross andrew@yipit.com wrote:

Some additional options instead of using file, just change the
notification.

execute “Set Permissions” do
command “chmod -R 644 /etc/foo/bar
action :nothing
only_if { ::File.exists?(”/etc/foo/bar/baz.conf")}
end

We can also outsource the directory spidering to Ruby (
http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby
)

Set files

Dir.glob("/etc/foo/**/*").each do |f|
file “Set permissions for #{f}” do
mode 00644
action :create
end if ::File.exists?("/etc/foo")

Set Directories

Dir.glob("/etc/foo/**/*/").each do |d|
directory “Set permissions for #{d}” do
mode 00755
action :create
end if ::File.exists?("/etc/foo")

On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Andrew,

First, thanks for the quick response. It’s always a bit nerve-wracking
submitting your first question to a new mailing list.

It seems like if I go down that road, I’ll end up having to explicitly
define a file or directory resource for everything in the package, which
would leave me with a huge policy cookbook that may need a major overhaul
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply
writing a Ruby block that walks the tree of subdirectories and files at
execution time changing ownership and permission seems less “correct” than
using file and directory resources.

Chef isn’t psychic, so I have to believe that my attempt to dynamically
create file and directory resources during the compile phase for stuff that
won’t exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I’m just going to have to
write some execution phase code to walk through the file system and make
the necessary ownership and permission changes on the installed files and
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross andrew@yipit.com wrote:

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for
those
files can’t be dynamically generated in the compile phase. What is the
most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software bundle
(Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership
and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in
the policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM,
Chef
attempts to create the config file resources during the compile phase
but since
Mule doesn’t actually get installed until the execution phase, there
are no
config files for which to generate resources. It’s not a huge deal
with the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar
files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob


#7

Completely forgot about to embed in a ruby_block, definitely a better way
to do it.

On Fri, Oct 11, 2013 at 3:52 PM, steve . leftathome@gmail.com wrote:

The difference between your excerpt and Rob’s is that his is wrapped in a
ruby_block resource. Your code will be evaluated (and, therefore, the
directory will be walked) during the compile phase … for Rob’s particular
scenario, he wants the directory walk (and resource creation) to take place
after the package is present.

So if he did things your way, it would take two Chef runs to obtain the
desired end state.

I have the feeling everyone on this thread already knew this, but I
thought I’d clarify this for the sake of posterity (i.e. whoever finds this
example via search engine).

On Fri, Oct 11, 2013 at 10:25 AM, Andrew Gross andrew@yipit.com wrote:

Some additional options instead of using file, just change the
notification.

execute “Set Permissions” do
command “chmod -R 644 /etc/foo/bar
action :nothing
only_if { ::File.exists?(”/etc/foo/bar/baz.conf")}
end

We can also outsource the directory spidering to Ruby (
http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby
)

Set files

Dir.glob("/etc/foo/**/*").each do |f|
file “Set permissions for #{f}” do
mode 00644
action :create
end if ::File.exists?("/etc/foo")

Set Directories

Dir.glob("/etc/foo/**/*/").each do |d|
directory “Set permissions for #{d}” do
mode 00755
action :create
end if ::File.exists?("/etc/foo")

On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis robert.h.curtis@gmail.comwrote:

Andrew,

First, thanks for the quick response. It’s always a bit nerve-wracking
submitting your first question to a new mailing list.

It seems like if I go down that road, I’ll end up having to explicitly
define a file or directory resource for everything in the package, which
would leave me with a huge policy cookbook that may need a major overhaul
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply
writing a Ruby block that walks the tree of subdirectories and files at
execution time changing ownership and permission seems less “correct” than
using file and directory resources.

Chef isn’t psychic, so I have to believe that my attempt to dynamically
create file and directory resources during the compile phase for stuff that
won’t exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I’m just going to have to
write some execution phase code to walk through the file system and make
the necessary ownership and permission changes on the installed files and
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross andrew@yipit.com wrote:

Hey Rob,

The normal pattern for this sort of thing is to have the post install
modification use ‘action :nothing’ and then send them a notification from
the package install to kick off a chain of events. Something similar to
this:

package “foo” do
version "bar"
action :install
notifies :create, “file[/etc/foo/bar]”, :immediately
end

file “/etc/foo/bar” do
mode 00644
action :nothing
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis <robert.h.curtis@gmail.com

wrote:

Executive Summary:
I’m using Chef to install a package and then update (ownership,
permissions)
many of the files installed with the package. Because the files don’t
exist
before the package is installed in the execution phase, resources for
those
files can’t be dynamically generated in the compile phase. What is
the most
correct (idempotent, efficient) way to update the package’s files after
install? Do I just use a Ruby block to chown/chmod the files? Do I
create an
explicit resource for each and every file?

The longer version:
We are using Chef to install and configure a particular software
bundle (Mule
ESB). In keeping with what we understand to be the best practices, we
have a
library cookbook that simply does the bare-bones install and a policy
cookbook
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the
ownership and
permissions on many of the files that get installed by the library
cookbook to
make our security guys happy. My first cut at the default recipe in
the policy
cookbook looks something like this:

Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

Install Mule

include_recipe “mule”

Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

Remove example applications

directory “#{node[:mule][:home]}/examples” do
recursive true
action :delete
end

Restrict access to config files

Dir[ “#{node[:mule][:home]}/conf/*” ].each do |path|
file path do
owner node[:mule-policy][:user]
group node[:mule-policy][:group]
mode "0640"
end if File.file?(path)
end

End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM,
Chef
attempts to create the config file resources during the compile phase
but since
Mule doesn’t actually get installed until the execution phase, there
are no
config files for which to generate resources. It’s not a huge deal
with the
config files since there are only 3 of them, but it’s a bigger problem
when we
start getting into the /lib directory, which contains dozens of .jar
files and
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob