chef 0.10.8 → 0.10.10.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/distro/arch/etc/rc.d/chef-client +15 -1
- data/distro/common/html/chef-client.8.html +4 -4
- data/distro/common/html/chef-expander.8.html +4 -4
- data/distro/common/html/chef-expanderctl.8.html +4 -4
- data/distro/common/html/chef-server-webui.8.html +4 -4
- data/distro/common/html/chef-server.8.html +4 -4
- data/distro/common/html/chef-solo.8.html +4 -4
- data/distro/common/html/chef-solr.8.html +4 -4
- data/distro/common/html/knife-bootstrap.1.html +6 -10
- data/distro/common/html/knife-client.1.html +4 -4
- data/distro/common/html/knife-configure.1.html +4 -4
- data/distro/common/html/knife-cookbook-site.1.html +6 -6
- data/distro/common/html/knife-cookbook.1.html +4 -4
- data/distro/common/html/knife-data-bag.1.html +4 -4
- data/distro/common/html/knife-environment.1.html +4 -4
- data/distro/common/html/knife-exec.1.html +4 -4
- data/distro/common/html/knife-index.1.html +4 -4
- data/distro/common/html/knife-node.1.html +5 -5
- data/distro/common/html/knife-role.1.html +4 -4
- data/distro/common/html/knife-search.1.html +4 -4
- data/distro/common/html/knife-ssh.1.html +5 -6
- data/distro/common/html/knife-status.1.html +4 -4
- data/distro/common/html/knife-tag.1.html +4 -4
- data/distro/common/html/knife.1.html +7 -8
- data/distro/common/html/shef.1.html +4 -4
- data/distro/common/man/man1/knife-bootstrap.1 +4 -4
- data/distro/common/man/man1/knife-client.1 +1 -1
- data/distro/common/man/man1/knife-configure.1 +1 -1
- data/distro/common/man/man1/knife-cookbook-site.1 +4 -4
- data/distro/common/man/man1/knife-cookbook.1 +1 -1
- data/distro/common/man/man1/knife-data-bag.1 +1 -1
- data/distro/common/man/man1/knife-environment.1 +1 -1
- data/distro/common/man/man1/knife-exec.1 +1 -1
- data/distro/common/man/man1/knife-index.1 +1 -1
- data/distro/common/man/man1/knife-node.1 +2 -2
- data/distro/common/man/man1/knife-role.1 +1 -1
- data/distro/common/man/man1/knife-search.1 +1 -1
- data/distro/common/man/man1/knife-ssh.1 +3 -7
- data/distro/common/man/man1/knife-status.1 +1 -1
- data/distro/common/man/man1/knife-tag.1 +1 -1
- data/distro/common/man/man1/knife.1 +5 -9
- data/distro/common/man/man1/shef.1 +1 -1
- data/distro/common/man/man8/chef-client.8 +1 -1
- data/distro/common/man/man8/chef-expander.8 +1 -1
- data/distro/common/man/man8/chef-expanderctl.8 +1 -1
- data/distro/common/man/man8/chef-server-webui.8 +1 -1
- data/distro/common/man/man8/chef-server.8 +1 -1
- data/distro/common/man/man8/chef-solo.8 +1 -1
- data/distro/common/man/man8/chef-solr.8 +1 -1
- data/distro/common/markdown/man1/knife-bootstrap.mkd +3 -7
- data/distro/common/markdown/man1/knife-cookbook-site.mkd +3 -3
- data/distro/common/markdown/man1/knife-node.mkd +2 -2
- data/distro/common/markdown/man1/knife-ssh.mkd +2 -5
- data/distro/common/markdown/man1/knife.mkd +7 -9
- data/distro/debian/etc/init.d/chef-client +22 -1
- data/distro/redhat/etc/init.d/chef-client +12 -1
- data/distro/windows/service_manager.rb +164 -0
- data/lib/chef/application.rb +12 -6
- data/lib/chef/application/client.rb +4 -3
- data/lib/chef/application/knife.rb +7 -12
- data/lib/chef/application/solo.rb +2 -1
- data/lib/chef/application/windows_service.rb +224 -0
- data/lib/chef/checksum_cache.rb +1 -0
- data/lib/chef/client.rb +3 -16
- data/lib/chef/config.rb +42 -13
- data/lib/chef/cookbook/metadata.rb +1 -1
- data/lib/chef/cookbook/syntax_check.rb +2 -2
- data/lib/chef/cookbook_version.rb +5 -0
- data/lib/chef/daemon.rb +1 -1
- data/lib/chef/exceptions.rb +7 -1
- data/lib/chef/file_access_control.rb +13 -87
- data/lib/chef/file_access_control/unix.rb +119 -0
- data/lib/chef/file_access_control/windows.rb +257 -0
- data/lib/chef/handler/json_file.rb +7 -1
- data/lib/chef/knife.rb +10 -16
- data/lib/chef/knife/bootstrap.rb +15 -8
- data/lib/chef/knife/bootstrap/centos5-gems.erb +1 -1
- data/lib/chef/knife/bootstrap/chef-full.erb +59 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +1 -0
- data/lib/chef/knife/configure.rb +2 -2
- data/lib/chef/knife/cookbook_site_download.rb +60 -21
- data/lib/chef/knife/cookbook_site_install.rb +16 -21
- data/lib/chef/knife/cookbook_upload.rb +77 -48
- data/lib/chef/knife/core/bootstrap_context.rb +3 -1
- data/lib/chef/knife/core/cookbook_scm_repo.rb +1 -1
- data/lib/chef/knife/core/node_editor.rb +1 -1
- data/lib/chef/knife/core/subcommand_loader.rb +1 -1
- data/lib/chef/knife/core/ui.rb +3 -2
- data/lib/chef/knife/help_topics.rb +1 -1
- data/lib/chef/knife/node_run_list_add.rb +14 -6
- data/lib/chef/knife/node_run_list_remove.rb +3 -3
- data/lib/chef/knife/ssh.rb +32 -13
- data/lib/chef/mash.rb +14 -0
- data/lib/chef/mixin/command.rb +1 -0
- data/lib/chef/mixin/command/unix.rb +5 -0
- data/lib/chef/mixin/convert_to_class_name.rb +2 -0
- data/lib/chef/mixin/deep_merge.rb +40 -18
- data/lib/chef/mixin/enforce_ownership_and_permissions.rb +39 -0
- data/lib/chef/mixin/language.rb +89 -3
- data/lib/chef/mixin/language_include_recipe.rb +8 -4
- data/lib/chef/mixin/path_sanity.rb +67 -0
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +19 -11
- data/lib/chef/mixin/securable.rb +152 -0
- data/lib/chef/mixin/shell_out.rb +1 -1
- data/lib/chef/mixin/template.rb +8 -3
- data/lib/chef/mixins.rb +3 -0
- data/lib/chef/monkey_patches/moneta.rb +50 -0
- data/lib/chef/monkey_patches/string.rb +1 -1
- data/lib/chef/node.rb +2 -1
- data/lib/chef/platform.rb +34 -0
- data/lib/chef/provider.rb +23 -21
- data/lib/chef/provider/cron.rb +17 -12
- data/lib/chef/provider/cron/solaris.rb +6 -18
- data/lib/chef/provider/deploy.rb +14 -15
- data/lib/chef/provider/deploy/timestamped.rb +0 -1
- data/lib/chef/provider/directory.rb +1 -3
- data/lib/chef/provider/execute.rb +2 -2
- data/lib/chef/provider/file.rb +1 -75
- data/lib/chef/provider/git.rb +11 -9
- data/lib/chef/provider/group/gpasswd.rb +14 -9
- data/lib/chef/provider/link.rb +28 -59
- data/lib/chef/provider/mdadm.rb +2 -2
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/package.rb +10 -6
- data/lib/chef/provider/package/apt.rb +3 -1
- data/lib/chef/provider/package/dpkg.rb +1 -1
- data/lib/chef/provider/package/portage.rb +6 -3
- data/lib/chef/provider/package/rubygems.rb +75 -6
- data/lib/chef/provider/package/smartos.rb +84 -0
- data/lib/chef/provider/package/yum-dump.py +3 -2
- data/lib/chef/provider/package/yum.rb +51 -10
- data/lib/chef/provider/remote_directory.rb +24 -3
- data/lib/chef/provider/remote_file.rb +0 -6
- data/lib/chef/provider/route.rb +3 -3
- data/lib/chef/provider/service/debian.rb +2 -2
- data/lib/chef/provider/service/freebsd.rb +1 -1
- data/lib/chef/provider/service/macosx.rb +125 -0
- data/lib/chef/provider/service/windows.rb +5 -1
- data/lib/chef/provider/subversion.rb +10 -7
- data/lib/chef/providers.rb +3 -0
- data/lib/chef/resource.rb +181 -87
- data/lib/chef/resource/apt_package.rb +10 -1
- data/lib/chef/resource/chef_gem.rb +53 -0
- data/lib/chef/resource/conditional.rb +3 -0
- data/lib/chef/resource/cookbook_file.rb +12 -6
- data/lib/chef/resource/cron.rb +9 -0
- data/lib/chef/resource/directory.rb +14 -31
- data/lib/chef/resource/execute.rb +11 -9
- data/lib/chef/resource/file.rb +9 -33
- data/lib/chef/resource/link.rb +13 -8
- data/lib/chef/resource/mdadm.rb +10 -1
- data/lib/chef/resource/remote_directory.rb +13 -2
- data/lib/chef/resource/remote_file.rb +14 -7
- data/lib/chef/resource/smartos_package.rb +36 -0
- data/lib/chef/resource/template.rb +12 -5
- data/lib/chef/resource_platform_map.rb +153 -0
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +55 -10
- data/lib/chef/rest/auth_credentials.rb +1 -0
- data/lib/chef/rest/rest_request.rb +24 -8
- data/lib/chef/role.rb +8 -2
- data/lib/chef/run_list.rb +1 -1
- data/lib/chef/run_list/run_list_expansion.rb +2 -2
- data/lib/chef/run_list/run_list_item.rb +7 -0
- data/lib/chef/runner.rb +4 -0
- data/lib/chef/shef.rb +2 -2
- data/lib/chef/shef/shef_session.rb +4 -5
- data/lib/chef/shell_out.rb +2 -245
- data/lib/chef/util/file_edit.rb +99 -89
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api.rb +349 -0
- data/lib/chef/win32/api/error.rb +921 -0
- data/lib/chef/win32/api/file.rb +289 -0
- data/lib/chef/win32/api/memory.rb +105 -0
- data/lib/chef/win32/api/process.rb +40 -0
- data/lib/chef/win32/api/psapi.rb +51 -0
- data/lib/chef/win32/api/security.rb +341 -0
- data/lib/chef/win32/api/system.rb +192 -0
- data/lib/chef/win32/api/unicode.rb +178 -0
- data/lib/chef/win32/error.rb +73 -0
- data/lib/chef/win32/file.rb +117 -0
- data/lib/chef/win32/file/info.rb +100 -0
- data/lib/chef/win32/handle.rb +48 -0
- data/lib/chef/win32/memory.rb +101 -0
- data/lib/chef/win32/process.rb +84 -0
- data/lib/chef/win32/security.rb +489 -0
- data/lib/chef/win32/security/ace.rb +125 -0
- data/lib/chef/win32/security/acl.rb +101 -0
- data/lib/chef/win32/security/securable_object.rb +109 -0
- data/lib/chef/win32/security/security_descriptor.rb +93 -0
- data/lib/chef/win32/security/sid.rb +199 -0
- data/lib/chef/win32/security/token.rb +64 -0
- data/lib/chef/win32/unicode.rb +43 -0
- data/lib/chef/win32/version.rb +119 -0
- metadata +104 -158
- data/lib/chef/shell_out/unix.rb +0 -223
- data/lib/chef/shell_out/windows.rb +0 -588
@@ -91,7 +91,7 @@ class Chef
|
|
91
91
|
#
|
92
92
|
# === Returns
|
93
93
|
# metadata<Chef::Cookbook::Metadata>
|
94
|
-
def initialize(cookbook=nil, maintainer='
|
94
|
+
def initialize(cookbook=nil, maintainer='YOUR_COMPANY_NAME', maintainer_email='YOUR_EMAIL', license='none')
|
95
95
|
@cookbook = cookbook
|
96
96
|
@name = cookbook ? cookbook.name : ""
|
97
97
|
@long_description = ""
|
@@ -112,7 +112,7 @@ class Chef
|
|
112
112
|
result = shell_out("erubis -x #{erb_file} | ruby -c")
|
113
113
|
result.error!
|
114
114
|
true
|
115
|
-
rescue
|
115
|
+
rescue Mixlib::ShellOut::ShellCommandFailed
|
116
116
|
file_relative_path = erb_file[/^#{Regexp.escape(cookbook_path+File::Separator)}(.*)/, 1]
|
117
117
|
Chef::Log.fatal("Erb template #{file_relative_path} has a syntax error:")
|
118
118
|
result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
|
@@ -124,7 +124,7 @@ class Chef
|
|
124
124
|
result = shell_out("ruby -c #{ruby_file}")
|
125
125
|
result.error!
|
126
126
|
true
|
127
|
-
rescue
|
127
|
+
rescue Mixlib::ShellOut::ShellCommandFailed
|
128
128
|
file_relative_path = ruby_file[/^#{Regexp.escape(cookbook_path+File::Separator)}(.*)/, 1]
|
129
129
|
Chef::Log.fatal("Cookbook file #{file_relative_path} has a ruby syntax error:")
|
130
130
|
result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
|
@@ -875,10 +875,15 @@ class Chef
|
|
875
875
|
chef_server_rest.get_rest("cookbooks/#{name}/#{version}")
|
876
876
|
end
|
877
877
|
|
878
|
+
# The API returns only a single version of each cookbook in the result from the cookbooks method
|
878
879
|
def self.list
|
879
880
|
chef_server_rest.get_rest('cookbooks')
|
880
881
|
end
|
881
882
|
|
883
|
+
def self.list_all_versions
|
884
|
+
chef_server_rest.get_rest('cookbooks?num_versions=all')
|
885
|
+
end
|
886
|
+
|
882
887
|
##
|
883
888
|
# Given a +cookbook_name+, get a list of all versions that exist on the
|
884
889
|
# server.
|
data/lib/chef/daemon.rb
CHANGED
@@ -40,7 +40,7 @@ class Chef
|
|
40
40
|
exit if fork
|
41
41
|
Process.setsid
|
42
42
|
exit if fork
|
43
|
-
Chef::Log.info("Forked, in #{Process.pid}.
|
43
|
+
Chef::Log.info("Forked, in #{Process.pid}. Privileges: #{Process.euid} #{Process.egid}")
|
44
44
|
File.umask Chef::Config[:umask]
|
45
45
|
$stdin.reopen("/dev/null")
|
46
46
|
$stdout.reopen("/dev/null", "a")
|
data/lib/chef/exceptions.rb
CHANGED
@@ -49,6 +49,7 @@ class Chef
|
|
49
49
|
class ConfigurationError < ArgumentError; end
|
50
50
|
class RedirectLimitExceeded < RuntimeError; end
|
51
51
|
class AmbiguousRunlistSpecification < ArgumentError; end
|
52
|
+
class CookbookFrozen < ArgumentError; end
|
52
53
|
class CookbookNotFound < RuntimeError; end
|
53
54
|
# Cookbook loader used to raise an argument error when cookbook not found.
|
54
55
|
# for back compat, need to raise an error that inherits from ArgumentError
|
@@ -56,7 +57,6 @@ class Chef
|
|
56
57
|
class AttributeNotFound < RuntimeError; end
|
57
58
|
class InvalidCommandOption < RuntimeError; end
|
58
59
|
class CommandTimeout < RuntimeError; end
|
59
|
-
class ShellCommandFailed < RuntimeError; end
|
60
60
|
class RequestedUIDUnavailable < RuntimeError; end
|
61
61
|
class InvalidHomeDirectory < ArgumentError; end
|
62
62
|
class DsclCommandFailed < RuntimeError; end
|
@@ -74,6 +74,8 @@ class Chef
|
|
74
74
|
class InvalidDataBagItemID < ArgumentError; end
|
75
75
|
class InvalidDataBagName < ArgumentError; end
|
76
76
|
class EnclosingDirectoryDoesNotExist < ArgumentError; end
|
77
|
+
# Errors originating from calls to the Win32 API
|
78
|
+
class Win32APIError < RuntimeError; end
|
77
79
|
|
78
80
|
class ObsoleteDependencySyntax < ArgumentError; end
|
79
81
|
class InvalidDataBagPath < ArgumentError; end
|
@@ -89,6 +91,10 @@ class Chef
|
|
89
91
|
# match OP VERSION. ArgumentError?
|
90
92
|
class InvalidVersionConstraint < ArgumentError; end
|
91
93
|
|
94
|
+
# Backcompat with Chef::ShellOut code:
|
95
|
+
require 'mixlib/shellout/exceptions'
|
96
|
+
class ShellCommandFailed < Mixlib::ShellOut::ShellCommandFailed; end
|
97
|
+
|
92
98
|
class CookbookVersionSelection
|
93
99
|
|
94
100
|
# Compound exception: In run_list expansion and resolution,
|
@@ -25,13 +25,18 @@ class Chef
|
|
25
25
|
# FileAccessControl objects set the owner, group and mode of +file+ to
|
26
26
|
# the values specified by a value object, usually a Chef::Resource.
|
27
27
|
class FileAccessControl
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
|
29
|
+
if RUBY_PLATFORM =~ /mswin|mingw|windows/
|
30
|
+
require 'chef/file_access_control/windows'
|
31
|
+
include FileAccessControl::Windows
|
32
|
+
else
|
33
|
+
require 'chef/file_access_control/unix'
|
34
|
+
include FileAccessControl::Unix
|
35
|
+
end
|
36
|
+
|
31
37
|
attr_reader :resource
|
32
|
-
|
33
38
|
attr_reader :file
|
34
|
-
|
39
|
+
|
35
40
|
# FileAccessControl objects set the owner, group and mode of +file+ to
|
36
41
|
# the values specified by +resource+. +file+ is completely independent
|
37
42
|
# of any file or path attribute on +resource+, so it is possible to set
|
@@ -46,92 +51,13 @@ class Chef
|
|
46
51
|
@resource, @file = resource, file
|
47
52
|
@modified = false
|
48
53
|
end
|
49
|
-
|
54
|
+
|
50
55
|
def modified?
|
51
56
|
@modified
|
52
57
|
end
|
53
|
-
|
54
|
-
def set_all
|
55
|
-
set_owner
|
56
|
-
set_group
|
57
|
-
set_mode
|
58
|
-
end
|
59
|
-
|
60
|
-
# Workaround the fact that Ruby's Etc module doesn't believe in negative
|
61
|
-
# uids, so negative uids show up as the diminished radix complement of
|
62
|
-
# a uint. For example, a uid of -2 is reported as 4294967294
|
63
|
-
def diminished_radix_complement(int)
|
64
|
-
if int > UID_MAX
|
65
|
-
int - UINT
|
66
|
-
else
|
67
|
-
int
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def target_uid
|
72
|
-
return nil if resource.owner.nil?
|
73
|
-
if resource.owner.kind_of?(String)
|
74
|
-
diminished_radix_complement( Etc.getpwnam(resource.owner).uid )
|
75
|
-
elsif resource.owner.kind_of?(Integer)
|
76
|
-
resource.owner
|
77
|
-
else
|
78
|
-
Chef::Log.error("The `owner` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
|
79
|
-
raise ArgumentError, "cannot resolve #{resource.owner.inspect} to uid, owner must be a string or integer"
|
80
|
-
end
|
81
|
-
rescue ArgumentError
|
82
|
-
raise Chef::Exceptions::UserIDNotFound, "cannot determine user id for '#{resource.owner}', does the user exist on this system?"
|
83
|
-
end
|
84
|
-
|
85
|
-
def set_owner
|
86
|
-
if (uid = target_uid) && (uid != stat.uid)
|
87
|
-
File.chown(uid, nil, file)
|
88
|
-
Chef::Log.info("#{log_string} owner changed to #{uid}")
|
89
|
-
modified
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def target_gid
|
94
|
-
return nil if resource.group.nil?
|
95
|
-
if resource.group.kind_of?(String)
|
96
|
-
diminished_radix_complement( Etc.getgrnam(resource.group).gid )
|
97
|
-
elsif resource.group.kind_of?(Integer)
|
98
|
-
resource.group
|
99
|
-
else
|
100
|
-
Chef::Log.error("The `group` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
|
101
|
-
raise ArgumentError, "cannot resolve #{resource.group.inspect} to gid, group must be a string or integer"
|
102
|
-
end
|
103
|
-
rescue ArgumentError
|
104
|
-
raise Chef::Exceptions::GroupIDNotFound, "cannot determine group id for '#{resource.group}', does the group exist on this system?"
|
105
|
-
end
|
106
|
-
|
107
|
-
def set_group
|
108
|
-
if (gid = target_gid) && (gid != stat.gid)
|
109
|
-
File.chown(nil, gid, file)
|
110
|
-
Chef::Log.info("#{log_string} group changed to #{gid}")
|
111
|
-
modified
|
112
|
-
end
|
113
|
-
end
|
114
58
|
|
115
|
-
def target_mode
|
116
|
-
return nil if resource.mode.nil?
|
117
|
-
(resource.mode.respond_to?(:oct) ? resource.mode.oct : resource.mode.to_i) & 007777
|
118
|
-
end
|
119
|
-
|
120
|
-
def set_mode
|
121
|
-
if (mode = target_mode) && (mode != (stat.mode & 007777))
|
122
|
-
File.chmod(target_mode, file)
|
123
|
-
Chef::Log.info("#{log_string} mode changed to #{mode.to_s(8)}")
|
124
|
-
modified
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
def stat
|
130
|
-
@stat ||= ::File.stat(file)
|
131
|
-
end
|
132
|
-
|
133
59
|
private
|
134
|
-
|
60
|
+
|
135
61
|
def modified
|
136
62
|
@modified = true
|
137
63
|
end
|
@@ -139,6 +65,6 @@ class Chef
|
|
139
65
|
def log_string
|
140
66
|
@resource || @file
|
141
67
|
end
|
142
|
-
|
68
|
+
|
143
69
|
end
|
144
70
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Daniel DeLeo (<dan@opscode.com>)
|
4
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2008-2011 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'chef/log'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class FileAccessControl
|
25
|
+
module Unix
|
26
|
+
UINT = (1 << 32)
|
27
|
+
UID_MAX = (1 << 32) - 10
|
28
|
+
|
29
|
+
def set_all
|
30
|
+
set_owner
|
31
|
+
set_group
|
32
|
+
set_mode unless resource.instance_of?(Chef::Resource::Link)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Workaround the fact that Ruby's Etc module doesn't believe in negative
|
36
|
+
# uids, so negative uids show up as the diminished radix complement of
|
37
|
+
# a uint. For example, a uid of -2 is reported as 4294967294
|
38
|
+
def diminished_radix_complement(int)
|
39
|
+
if int > UID_MAX
|
40
|
+
int - UINT
|
41
|
+
else
|
42
|
+
int
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def target_uid
|
47
|
+
return nil if resource.owner.nil?
|
48
|
+
if resource.owner.kind_of?(String)
|
49
|
+
diminished_radix_complement( Etc.getpwnam(resource.owner).uid )
|
50
|
+
elsif resource.owner.kind_of?(Integer)
|
51
|
+
resource.owner
|
52
|
+
else
|
53
|
+
Chef::Log.error("The `owner` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
|
54
|
+
raise ArgumentError, "cannot resolve #{resource.owner.inspect} to uid, owner must be a string or integer"
|
55
|
+
end
|
56
|
+
rescue ArgumentError
|
57
|
+
raise Chef::Exceptions::UserIDNotFound, "cannot determine user id for '#{resource.owner}', does the user exist on this system?"
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_owner
|
61
|
+
if (uid = target_uid) && (uid != stat.uid)
|
62
|
+
chown(uid, nil, file)
|
63
|
+
Chef::Log.info("#{log_string} owner changed to #{uid}")
|
64
|
+
modified
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def target_gid
|
69
|
+
return nil if resource.group.nil?
|
70
|
+
if resource.group.kind_of?(String)
|
71
|
+
diminished_radix_complement( Etc.getgrnam(resource.group).gid )
|
72
|
+
elsif resource.group.kind_of?(Integer)
|
73
|
+
resource.group
|
74
|
+
else
|
75
|
+
Chef::Log.error("The `group` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
|
76
|
+
raise ArgumentError, "cannot resolve #{resource.group.inspect} to gid, group must be a string or integer"
|
77
|
+
end
|
78
|
+
rescue ArgumentError
|
79
|
+
raise Chef::Exceptions::GroupIDNotFound, "cannot determine group id for '#{resource.group}', does the group exist on this system?"
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_group
|
83
|
+
if (gid = target_gid) && (gid != stat.gid)
|
84
|
+
chown(nil, gid, file)
|
85
|
+
Chef::Log.info("#{log_string} group changed to #{gid}")
|
86
|
+
modified
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# TODO rename this to a more generic target_permissions
|
91
|
+
def target_mode
|
92
|
+
return nil if resource.mode.nil?
|
93
|
+
(resource.mode.respond_to?(:oct) ? resource.mode.oct : resource.mode.to_i) & 007777
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO rename this to a more generic set_permissions
|
97
|
+
def set_mode
|
98
|
+
if (mode = target_mode) && (mode != (stat.mode & 007777))
|
99
|
+
File.chmod(target_mode, file)
|
100
|
+
Chef::Log.info("#{log_string} mode changed to #{mode.to_s(8)}")
|
101
|
+
modified
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def stat
|
106
|
+
@stat ||= ::File.stat(file)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
def chown(uid, gid, file)
|
111
|
+
if resource.instance_of?(Chef::Resource::Link)
|
112
|
+
File.lchown(uid, gid, file)
|
113
|
+
else
|
114
|
+
File.chown(uid, gid, file)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
#
|
2
|
+
# Author:: John Keiser (<jkeiser@opscode.com>)
|
3
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
4
|
+
# Copyright:: Copyright 2011 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef/win32/security'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class FileAccessControl
|
24
|
+
module Windows
|
25
|
+
include Chef::Win32::API::Security
|
26
|
+
|
27
|
+
Security = Chef::Win32::Security
|
28
|
+
ACL = Security::ACL
|
29
|
+
ACE = Security::ACE
|
30
|
+
SID = Security::SID
|
31
|
+
|
32
|
+
def set_all
|
33
|
+
set_owner
|
34
|
+
set_group
|
35
|
+
set_dacl
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Compare the actual ACL on a resource with the ACL we want. This
|
41
|
+
# ignores explicit ACLs on the target, and does mask prediction (if you
|
42
|
+
# set GENERIC_WRITE, Windows will flip on a whole bunch of other rights
|
43
|
+
# on the file when you save the ACL)
|
44
|
+
def acls_equal(target_acl, actual_acl)
|
45
|
+
if actual_acl.nil?
|
46
|
+
return target_acl.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
actual_acl = actual_acl.select { |ace| !ace.inherited? }
|
50
|
+
# When ACLs apply to children, Windows splits them on the file system into two ACLs:
|
51
|
+
# one specific applying to this container, and one generic applying to children.
|
52
|
+
new_target_acl = []
|
53
|
+
target_acl.each do |target_ace|
|
54
|
+
if target_ace.flags & INHERIT_ONLY_ACE == 0
|
55
|
+
self_ace = target_ace.dup
|
56
|
+
self_ace.flags = 0
|
57
|
+
self_ace.mask = securable_object.predict_rights_mask(target_ace.mask)
|
58
|
+
new_target_acl << self_ace
|
59
|
+
end
|
60
|
+
if target_ace.flags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE) != 0
|
61
|
+
children_ace = target_ace.dup
|
62
|
+
children_ace.flags |= INHERIT_ONLY_ACE
|
63
|
+
new_target_acl << children_ace
|
64
|
+
end
|
65
|
+
end
|
66
|
+
return actual_acl == new_target_acl
|
67
|
+
end
|
68
|
+
|
69
|
+
def existing_descriptor
|
70
|
+
securable_object.security_descriptor
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_sid(value)
|
74
|
+
if value.kind_of?(String)
|
75
|
+
SID.from_account(value)
|
76
|
+
elsif value.kind_of?(SID)
|
77
|
+
value
|
78
|
+
else
|
79
|
+
raise "Must specify username, group or SID: #{value}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def securable_object
|
84
|
+
@securable_object ||= begin
|
85
|
+
if file.kind_of?(String)
|
86
|
+
so = Chef::Win32::Security::SecurableObject.new(file.dup)
|
87
|
+
end
|
88
|
+
raise ArgumentError, "'file' must be a valid path or object of type 'Chef::Win32::Security::SecurableObject'" unless so.kind_of? Chef::Win32::Security::SecurableObject
|
89
|
+
so
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_dacl
|
94
|
+
dacl = target_dacl
|
95
|
+
existing_dacl = existing_descriptor.dacl
|
96
|
+
inherits = target_inherits
|
97
|
+
if ! inherits.nil? && inherits != existing_descriptor.dacl_inherits?
|
98
|
+
# We have to set DACL along with inherits. If rights were not
|
99
|
+
# specified, we need to change only inherited ACLs and leave
|
100
|
+
# explicit ACLs alone.
|
101
|
+
if dacl.nil? && !existing_dacl.nil?
|
102
|
+
dacl = ACL.create(existing_dacl.select { |ace| !ace.inherited? })
|
103
|
+
end
|
104
|
+
securable_object.set_dacl(dacl, inherits)
|
105
|
+
Chef::Log.info("#{log_string} permissions changed to #{dacl} with inherits of #{inherits}")
|
106
|
+
modified
|
107
|
+
elsif dacl && !acls_equal(dacl, existing_dacl)
|
108
|
+
securable_object.dacl = dacl
|
109
|
+
Chef::Log.info("#{log_string} permissions changed to #{dacl}")
|
110
|
+
modified
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def set_group
|
115
|
+
if (group = target_group) && (group != existing_descriptor.group)
|
116
|
+
Chef::Log.info("#{log_string} group changed to #{group}")
|
117
|
+
securable_object.group = group
|
118
|
+
modified
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_owner
|
123
|
+
if (owner = target_owner) && (owner != existing_descriptor.owner)
|
124
|
+
Chef::Log.info("#{log_string} owner changed to #{owner}")
|
125
|
+
securable_object.owner = owner
|
126
|
+
modified
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def mode_ace(sid, mode)
|
131
|
+
mask = 0
|
132
|
+
mask |= GENERIC_READ if mode & 4 != 0
|
133
|
+
mask |= (GENERIC_WRITE | DELETE) if mode & 2 != 0
|
134
|
+
mask |= GENERIC_EXECUTE if mode & 1 != 0
|
135
|
+
return [] if mask == 0
|
136
|
+
[ ACE.access_allowed(sid, mask) ]
|
137
|
+
end
|
138
|
+
|
139
|
+
def calculate_mask(permissions)
|
140
|
+
mask = 0
|
141
|
+
[ permissions ].flatten.each do |permission|
|
142
|
+
case permission
|
143
|
+
when :full_control
|
144
|
+
mask |= GENERIC_ALL
|
145
|
+
when :modify
|
146
|
+
mask |= GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE | DELETE
|
147
|
+
when :read
|
148
|
+
mask |= GENERIC_READ
|
149
|
+
when :read_execute
|
150
|
+
mask |= GENERIC_READ | GENERIC_EXECUTE
|
151
|
+
when :write
|
152
|
+
mask |= GENERIC_WRITE
|
153
|
+
else
|
154
|
+
# Otherwise, assume it's an integer specifying the actual flags
|
155
|
+
mask |= permission
|
156
|
+
end
|
157
|
+
end
|
158
|
+
mask
|
159
|
+
end
|
160
|
+
|
161
|
+
def calculate_flags(rights)
|
162
|
+
# Handle inheritance flags
|
163
|
+
flags = 0
|
164
|
+
case rights[:applies_to_children]
|
165
|
+
when :containers_only
|
166
|
+
flags |= CONTAINER_INHERIT_ACE
|
167
|
+
when :objects_only
|
168
|
+
flags |= OBJECT_INHERIT_ACE
|
169
|
+
when true
|
170
|
+
flags |= CONTAINER_INHERIT_ACE
|
171
|
+
flags |= OBJECT_INHERIT_ACE
|
172
|
+
when nil
|
173
|
+
flags |= CONTAINER_INHERIT_ACE
|
174
|
+
flags |= OBJECT_INHERIT_ACE
|
175
|
+
end
|
176
|
+
|
177
|
+
if rights[:applies_to_self] == false
|
178
|
+
flags |= INHERIT_ONLY_ACE
|
179
|
+
end
|
180
|
+
|
181
|
+
if rights[:one_level_deep]
|
182
|
+
flags |= NO_PROPAGATE_INHERIT_ACE
|
183
|
+
end
|
184
|
+
flags
|
185
|
+
end
|
186
|
+
|
187
|
+
def target_dacl
|
188
|
+
return nil if resource.rights.nil? && resource.deny_rights.nil? && resource.mode.nil?
|
189
|
+
acls = nil
|
190
|
+
|
191
|
+
if !resource.deny_rights.nil?
|
192
|
+
acls = [] if acls.nil?
|
193
|
+
|
194
|
+
resource.deny_rights.each do |rights|
|
195
|
+
mask = calculate_mask(rights[:permissions])
|
196
|
+
[ rights[:principals] ].flatten.each do |principal|
|
197
|
+
sid = get_sid(principal)
|
198
|
+
flags = calculate_flags(rights)
|
199
|
+
acls.push ACE.access_denied(sid, mask, flags)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
if !resource.rights.nil?
|
205
|
+
acls = [] if acls.nil?
|
206
|
+
|
207
|
+
resource.rights.each do |rights|
|
208
|
+
mask = calculate_mask(rights[:permissions])
|
209
|
+
[ rights[:principals] ].flatten.each do |principal|
|
210
|
+
sid = get_sid(principal)
|
211
|
+
flags = calculate_flags(rights)
|
212
|
+
acls.push ACE.access_allowed(sid, mask, flags)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
if !resource.mode.nil?
|
218
|
+
acls = [] if acls.nil?
|
219
|
+
|
220
|
+
mode = (resource.mode.respond_to?(:oct) ? resource.mode.oct : resource.mode.to_i) & 0777
|
221
|
+
|
222
|
+
owner = target_owner
|
223
|
+
if owner
|
224
|
+
acls += mode_ace(owner, (mode & 0700) >> 6)
|
225
|
+
elsif mode & 0700 != 0
|
226
|
+
raise "Mode #{mode.to_s(8)} includes bits for the owner, but owner is not specified"
|
227
|
+
end
|
228
|
+
|
229
|
+
group = target_group
|
230
|
+
if group
|
231
|
+
acls += mode_ace(group, (mode & 070) >> 3)
|
232
|
+
elsif mode & 070 != 0
|
233
|
+
raise "Mode #{mode.to_s(8)} includes bits for the group, but group is not specified"
|
234
|
+
end
|
235
|
+
|
236
|
+
acls += mode_ace(SID.Everyone, (mode & 07))
|
237
|
+
end
|
238
|
+
|
239
|
+
acls.nil? ? nil : Chef::Win32::Security::ACL.create(acls)
|
240
|
+
end
|
241
|
+
|
242
|
+
def target_group
|
243
|
+
return nil if resource.group.nil?
|
244
|
+
sid = get_sid(resource.group)
|
245
|
+
end
|
246
|
+
|
247
|
+
def target_inherits
|
248
|
+
resource.inherits
|
249
|
+
end
|
250
|
+
|
251
|
+
def target_owner
|
252
|
+
return nil if resource.owner.nil?
|
253
|
+
sid = get_sid(resource.owner)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|