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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
require 'puppet/provider/parsedfile'
Puppet::Type.type(:ssh_authorized_key).provide(:parsed,
:parent => Puppet::Provider::ParsedFile,
:filetype => :flat,
:default_target => ''
) do
desc "Parse and generate authorized_keys files for SSH."
text_line :comment, :match => /^#/
text_line :blank, :match => /^\s+/
record_line :parsed,
:fields => %w{options type key name},
:optional => %w{options},
:rts => /^\s+/,
:match => /^(?:(.+) )?(ssh-dss|ssh-rsa) ([^ ]+)(?: (.+))?$/,
:post_parse => proc { |record|
if record[:options].nil?
record[:options] = [:absent]
else
record[:options] = Puppet::Type::Ssh_authorized_key::ProviderParsed.parse_options(record[:options])
end
},
:pre_gen => proc { |record|
if record[:options].include?(:absent)
record[:options] = ""
else
record[:options] = record[:options].join(',')
end
}
record_line :key_v1,
:fields => %w{options bits exponent modulus name},
:optional => %w{options},
:rts => /^\s+/,
:match => /^(?:(.+) )?(\d+) (\d+) (\d+)(?: (.+))?$/
def target
@resource.should(:target)
end
def user
@resource.should(:user)
end
def dir_perm
# Determine correct permission for created directory and file
# we can afford more restrictive permissions when the user is known
if target
if user
0700
else
0755
end
end
end
def file_perm
if target
if user
0600
else
0644
end
end
end
def target
if user
File.expand_path("~%s/.ssh/authorized_keys" % user)
elsif target = @resource.should(:target)
target
end
end
def user
@resource.should(:user)
end
def dir_perm
# Determine correct permission for created directory and file
# we can afford more restrictive permissions when the user is known
if target
if user
0700
else
0755
end
end
end
def file_perm
if target
if user
0600
else
0644
end
end
end
def flush
# As path expansion had to be moved in the provider, we cannot generate new file
# resources and thus have to chown and chmod here. It smells hackish.
# Create target's parent directory if nonexistant
if target
dir = File.dirname(target)
if not File.exist? dir
Puppet.debug("Creating directory %s which did not exist" % dir)
Dir.mkdir(dir, dir_perm)
end
end
# Generate the file
super
# Ensure correct permissions
if target and user
uid = Puppet::Util.uid(user)
if uid
File.chown(uid, nil, dir)
File.chown(uid, nil, target)
else
raise Puppet::Error, "Specified user does not exist"
end
end
if target
File.chmod(file_perm, target)
end
end
# parse sshv2 option strings, wich is a comma separated list of
# either key="values" elements or bare-word elements
def self.parse_options(options)
result = []
scanner = StringScanner.new(options)
while !scanner.eos?
scanner.skip(/[ \t]*/)
# scan a long option
if out = scanner.scan(/[-a-z0-9A-Z_]+=\".*?\"/) or out = scanner.scan(/[-a-z0-9A-Z_]+/)
result << out
else
# found an unscannable token, let's abort
break
end
# eat a comma
scanner.skip(/[ \t]*,[ \t]*/)
end
result
end
end
|