1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#--
# Author:: Daniel DeLeo (<dan@opscode.com>)
# Copyright:: Copyright (c) 2012 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
class Chef
# == ScanAccessControl
# Reads Access Control Settings on a file and writes them out to a resource
# (should be the current_resource), attempting to match the style used by the
# new resource, that is, if users are specified with usernames in
# new_resource, then the uids from stat will be looked up and usernames will
# be added to current_resource.
#
# === Why?
# FileAccessControl objects may operate on a temporary file, in which case we
# won't know if the access control settings changed (ex: rendering a template
# with both a change in content and ownership). For auditing purposes, we
# need to record the current state of a file system entity.
#--
# Not yet sure if this is the optimal way to solve the problem. But it's
# progress towards the end goal.
#
# TODO: figure out if all this works with OS X's negative uids
# TODO: windows
class ScanAccessControl
attr_reader :new_resource
attr_reader :current_resource
def initialize(new_resource, current_resource)
@new_resource, @current_resource = new_resource, current_resource
end
# Modifies @current_resource, setting the current access control state.
def set_all!
if ::File.exist?(new_resource.path)
set_owner
set_group
set_mode
else
# leave the values as nil.
end
end
# Set the owner attribute of +current_resource+ to whatever the current
# state is. Attempts to match the format given in new_resource: if the
# new_resource specifies the owner as a string, the username for the uid
# will be looked up and owner will be set to the username, and vice versa.
def set_owner
@current_resource.owner(current_owner)
end
def current_owner
case new_resource.owner
when String, nil
lookup_uid
when Integer
stat.uid
else
Chef::Log.error("The `owner` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{new_resource.owner.inspect} to uid, owner must be a string or integer"
end
end
def lookup_uid
unless (pwent = Etc.getpwuid(stat.uid)).nil?
pwent.name
else
stat.uid
end
rescue ArgumentError
stat.uid
end
# Set the group attribute of +current_resource+ to whatever the current state is.
def set_group
@current_resource.group(current_group)
end
def current_group
case new_resource.group
when String, nil
lookup_gid
when Integer
stat.gid
else
Chef::Log.error("The `group` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{new_resource.group.inspect} to gid, group must be a string or integer"
end
end
def lookup_gid
unless (pwent = Etc.getgrgid(stat.gid)).nil?
pwent.name
else
stat.gid
end
rescue ArgumentError
stat.gid
end
def set_mode
@current_resource.mode(current_mode)
end
def current_mode
case new_resource.mode
when String, Integer, nil
"0#{(stat.mode & 07777).to_s(8)}"
else
Chef::Log.error("The `mode` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.mode.inspect})")
raise ArgumentError, "Invalid value #{new_resource.mode.inspect} for `mode` on resource #@new_resource"
end
end
def stat
@stat ||= if @new_resource.instance_of?(Chef::Resource::Link)
::File.lstat(@new_resource.path)
else
realpath = ::File.realpath(@new_resource.path)
::File.stat(realpath)
end
end
end
end
|