Advertisement
Guest User

Untitled

a guest
Mar 19th, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.25 KB | None | 0 0
  1. drwxr-xr-x 11 puppet puppet 4096 Mar 19 08:23 .
  2. drwxr-xr-x 3 root root 4096 Mar 19 08:23 ..
  3. drwxr-x--- 2 puppet puppet 4096 Mar 19 08:23 bucket
  4. drwxr-xr-x 2 root root 4096 Mar 19 08:23 facts.d
  5. drwxr-xr-x 2 root root 4096 Mar 19 08:23 lib
  6. drwxr-xr-x 2 root root 4096 Mar 19 08:23 locales
  7. drwxr-x--- 2 puppet puppet 4096 Mar 19 08:23 preview
  8. drwxr-x--- 2 puppet puppet 4096 Mar 19 08:23 reports
  9. drwxr-x--- 2 puppet puppet 4096 Mar 19 08:23 server_data
  10. drwxr-xr-t 2 root root 4096 Mar 19 08:23 state
  11. drwxr-x--- 2 puppet puppet 4096 Mar 19 08:23 yaml
  12. root@debian:~/puppetserver# ls vend
  13. ls: cannot access 'vend': No such file or directory
  14. root@debian:~/puppetserver# find . -type d -name "vendor*"
  15. ./ruby/puppet/lib/puppet/vendor
  16. root@debian:~/puppetserver# ls
  17. acceptance dev-cljs dev-setup ext Gemfile LICENSE.md MAINTAINERS project.clj README.md ruby src test
  18. dev dev-resources documentation ezbake jenkins locales Makefile Rakefile resources spec target
  19. root@debian:~/puppetserver# ls jenkins/
  20. deploy.sh
  21. root@debian:~/puppetserver# ls /root/.puppetlabs/opt/server/data/puppetserver/jruby-gems
  22. ls: cannot access '/root/.puppetlabs/opt/server/data/puppetserver/jruby-gems': No such file or directory
  23. root@debian:~/puppetserver# ls /root/.puppetlabs/opt/server/data
  24. ls: cannot access '/root/.puppetlabs/opt/server/data': No such file or directory
  25. root@debian:~/puppetserver# ls /root/.puppetlabs/opt/server/
  26. ls: cannot access '/root/.puppetlabs/opt/server/': No such file or directory
  27. root@debian:~/puppetserver# ls /root/.puppetlabs/opt
  28. puppet
  29. root@debian:~/puppetserver# ls /root/.puppetlabs/opt/puppet/
  30. cache
  31. root@debian:~/puppetserver# ls /root/.puppetlabs/opt/puppet/cache/
  32. bucket facts.d lib locales preview reports server_data state yaml
  33. root@debian:~/puppetserver# vi ruby/puppet/lib/puppettype/user/rb
  34. root@debian:~/puppetserver# vi ruby/puppet/lib/puppet/type/user.rb
  35. root@debian:~/puppetserver# file ruby/puppet/lib/puppet/type/user.rb
  36. ruby/puppet/lib/puppet/type/user.rb: Ruby module source, ASCII text
  37. root@debian:~/puppetserver# ls -l ruby/puppet/lib/puppet/type/user.rb
  38. -rw-r--r-- 1 root root 26787 Mar 19 08:12 ruby/puppet/lib/puppet/type/user.rb
  39. root@debian:~/puppetserver#
  40. root@debian:~/puppetserver# cat ruby/puppet/lib/puppet/type/user.rb
  41. require 'etc'
  42. require 'facter'
  43. require 'puppet/parameter/boolean'
  44. require 'puppet/property/list'
  45. require 'puppet/property/ordered_list'
  46. require 'puppet/property/keyvalue'
  47.  
  48. module Puppet
  49. Type.newtype(:user) do
  50. @doc = "Manage users. This type is mostly built to manage system
  51. users, so it is lacking some features useful for managing normal
  52. users.
  53.  
  54. This resource type uses the prescribed native tools for creating
  55. groups and generally uses POSIX APIs for retrieving information
  56. about them. It does not directly modify `/etc/passwd` or anything.
  57.  
  58. **Autorequires:** If Puppet is managing the user's primary group (as
  59. provided in the `gid` attribute) or any group listed in the `groups`
  60. attribute then the user resource will autorequire that group. If Puppet
  61. is managing any role accounts corresponding to the user's roles, the
  62. user resource will autorequire those role accounts."
  63.  
  64. feature :allows_duplicates,
  65. "The provider supports duplicate users with the same UID."
  66.  
  67. feature :manages_homedir,
  68. "The provider can create and remove home directories."
  69.  
  70. feature :manages_passwords,
  71. "The provider can modify user passwords, by accepting a password
  72. hash."
  73.  
  74. feature :manages_password_age,
  75. "The provider can set age requirements and restrictions for
  76. passwords."
  77.  
  78. feature :manages_password_salt,
  79. "The provider can set a password salt. This is for providers that
  80. implement PBKDF2 passwords with salt properties."
  81.  
  82. feature :manages_solaris_rbac,
  83. "The provider can manage roles and normal users"
  84.  
  85. feature :manages_expiry,
  86. "The provider can manage the expiry date for a user."
  87.  
  88. feature :system_users,
  89. "The provider allows you to create system users with lower UIDs."
  90.  
  91. feature :manages_aix_lam,
  92. "The provider can manage AIX Loadable Authentication Module (LAM) system."
  93.  
  94. feature :libuser,
  95. "Allows local users to be managed on systems that also use some other
  96. remote NSS method of managing accounts."
  97.  
  98. feature :manages_shell,
  99. "The provider allows for setting shell and validates if possible"
  100.  
  101. feature :manages_loginclass,
  102. "The provider can manage the login class for a user."
  103.  
  104. newproperty(:ensure, :parent => Puppet::Property::Ensure) do
  105. newvalue(:present, :event => :user_created) do
  106. provider.create
  107. end
  108.  
  109. newvalue(:absent, :event => :user_removed) do
  110. provider.delete
  111. end
  112.  
  113. newvalue(:role, :event => :role_created, :required_features => :manages_solaris_rbac) do
  114. provider.create_role
  115. end
  116.  
  117. desc "The basic state that the object should be in."
  118.  
  119. # If they're talking about the thing at all, they generally want to
  120. # say it should exist.
  121. defaultto do
  122. if @resource.managed?
  123. :present
  124. else
  125. nil
  126. end
  127. end
  128.  
  129. def retrieve
  130. if provider.exists?
  131. if provider.respond_to?(:is_role?) and provider.is_role?
  132. return :role
  133. else
  134. return :present
  135. end
  136. else
  137. return :absent
  138. end
  139. end
  140. end
  141.  
  142. newproperty(:home) do
  143. desc "The home directory of the user. The directory must be created
  144. separately and is not currently checked for existence."
  145. end
  146.  
  147. newproperty(:uid) do
  148. desc "The user ID; must be specified numerically. If no user ID is
  149. specified when creating a new user, then one will be chosen
  150. automatically. This will likely result in the same user having
  151. different UIDs on different systems, which is not recommended. This is
  152. especially noteworthy when managing the same user on both Darwin and
  153. other platforms, since Puppet does UID generation on Darwin, but
  154. the underlying tools do so on other platforms.
  155.  
  156. On Windows, this property is read-only and will return the user's
  157. security identifier (SID)."
  158.  
  159. munge do |value|
  160. case value
  161. when String
  162. if value =~ /^[-0-9]+$/
  163. value = Integer(value)
  164. end
  165. end
  166.  
  167. return value
  168. end
  169. end
  170.  
  171. newproperty(:gid) do
  172. desc "The user's primary group. Can be specified numerically or by name.
  173.  
  174. This attribute is not supported on Windows systems; use the `groups`
  175. attribute instead. (On Windows, designating a primary group is only
  176. meaningful for domain accounts, which Puppet does not currently manage.)"
  177.  
  178. munge do |value|
  179. if value.is_a?(String) and value =~ /^[-0-9]+$/
  180. Integer(value)
  181. else
  182. value
  183. end
  184. end
  185.  
  186. def insync?(is)
  187. # We know the 'is' is a number, so we need to convert the 'should' to a number,
  188. # too.
  189. @should.each do |value|
  190. return true if number = Puppet::Util.gid(value) and is == number
  191. end
  192.  
  193. false
  194. end
  195.  
  196. def sync
  197. found = false
  198. @should.each do |value|
  199. if number = Puppet::Util.gid(value)
  200. provider.gid = number
  201. found = true
  202. break
  203. end
  204. end
  205.  
  206. fail _("Could not find group(s) %{groups}") % { groups: @should.join(",") } unless found
  207.  
  208. # Use the default event.
  209. end
  210. end
  211.  
  212. newproperty(:comment) do
  213. desc "A description of the user. Generally the user's full name."
  214. def insync?(is)
  215. # nameservice provider requires special attention to encoding
  216. # Overrides Puppet::Property#insync?
  217. if !@should.empty? && provider.respond_to?(:comments_insync?)
  218. return provider.comments_insync?(is, @should)
  219. end
  220. super(is)
  221. end
  222.  
  223. # In the case that our comments have incompatible encodings, set external
  224. # encoding to support concatenation for display.
  225. # overrides Puppet::Property#change_to_s
  226. def change_to_s(currentvalue, newvalue)
  227. if newvalue.respond_to?(:force_encoding) && !Encoding.compatible?(currentvalue, newvalue)
  228. return super(currentvalue, newvalue.dup.force_encoding(currentvalue.encoding))
  229. end
  230. super(currentvalue, newvalue)
  231. end
  232. end
  233.  
  234. newproperty(:shell, :required_features => :manages_shell) do
  235. desc "The user's login shell. The shell must exist and be
  236. executable.
  237.  
  238. This attribute cannot be managed on Windows systems."
  239. end
  240.  
  241. newproperty(:password, :required_features => :manages_passwords) do
  242. desc %q{The user's password, in whatever encrypted format the local system
  243. requires. Consult your operating system's documentation for acceptable password
  244. encryption formats and requirements.
  245.  
  246. * Mac OS X 10.5 and 10.6, and some older Linux distributions, use salted SHA1
  247. hashes. You can use Puppet's built-in `sha1` function to generate a salted SHA1
  248. hash from a password.
  249. * Mac OS X 10.7 (Lion), and many recent Linux distributions, use salted SHA512
  250. hashes. The Puppet Labs [stdlib][] module contains a `str2saltedsha512` function
  251. which can generate password hashes for these operating systems.
  252. * OS X 10.8 and higher use salted SHA512 PBKDF2 hashes. When managing passwords
  253. on these systems, the `salt` and `iterations` attributes need to be specified as
  254. well as the password.
  255. * Windows passwords can only be managed in cleartext, as there is no Windows API
  256. for setting the password hash.
  257.  
  258. [stdlib]: https://github.com/puppetlabs/puppetlabs-stdlib/
  259.  
  260. Enclose any value that includes a dollar sign ($) in single quotes (') to avoid
  261. accidental variable interpolation.}
  262.  
  263. validate do |value|
  264. raise ArgumentError, _("Passwords cannot include ':'") if value.is_a?(String) and value.include?(":")
  265. end
  266.  
  267. def change_to_s(currentvalue, newvalue)
  268. if currentvalue == :absent
  269. return _("created password")
  270. else
  271. return _("changed password")
  272. end
  273. end
  274.  
  275. def is_to_s( currentvalue )
  276. return _('[old password hash redacted]')
  277. end
  278. def should_to_s( newvalue )
  279. return _('[new password hash redacted]')
  280. end
  281.  
  282. end
  283.  
  284. newproperty(:password_min_age, :required_features => :manages_password_age) do
  285. desc "The minimum number of days a password must be used before it may be changed."
  286.  
  287. munge do |value|
  288. case value
  289. when String
  290. Integer(value)
  291. else
  292. value
  293. end
  294. end
  295.  
  296. validate do |value|
  297. if value.to_s !~ /^-?\d+$/
  298. raise ArgumentError, _("Password minimum age must be provided as a number.")
  299. end
  300. end
  301. end
  302.  
  303. newproperty(:password_max_age, :required_features => :manages_password_age) do
  304. desc "The maximum number of days a password may be used before it must be changed."
  305.  
  306. munge do |value|
  307. case value
  308. when String
  309. Integer(value)
  310. else
  311. value
  312. end
  313. end
  314.  
  315. validate do |value|
  316. if value.to_s !~ /^-?\d+$/
  317. raise ArgumentError, _("Password maximum age must be provided as a number.")
  318. end
  319. end
  320. end
  321.  
  322. newproperty(:groups, :parent => Puppet::Property::List) do
  323. desc "The groups to which the user belongs. The primary group should
  324. not be listed, and groups should be identified by name rather than by
  325. GID. Multiple groups should be specified as an array."
  326.  
  327. validate do |value|
  328. if value =~ /^\d+$/
  329. raise ArgumentError, _("Group names must be provided, not GID numbers.")
  330. end
  331. raise ArgumentError, _("Group names must be provided as an array, not a comma-separated list.") if value.include?(",")
  332. raise ArgumentError, _("Group names must not be empty. If you want to specify \"no groups\" pass an empty array") if value.empty?
  333. end
  334.  
  335. def change_to_s(currentvalue, newvalue)
  336. newvalue = newvalue.split(",") if newvalue != :absent
  337.  
  338. if provider.respond_to?(:groups_to_s)
  339. # for Windows ADSI
  340. # de-dupe the "newvalue" when the sync event message is generated,
  341. # due to final retrieve called after the resource has been modified
  342. newvalue = provider.groups_to_s(newvalue).split(',').uniq
  343. end
  344.  
  345. super(currentvalue, newvalue)
  346. end
  347.  
  348. # override Puppet::Property::List#retrieve
  349. def retrieve
  350. if provider.respond_to?(:groups_to_s)
  351. # Windows ADSI groups returns SIDs, but retrieve needs names
  352. # must return qualified names for SIDs for "is" value and puppet resource
  353. return provider.groups_to_s(provider.groups).split(',')
  354. end
  355.  
  356. super
  357. end
  358.  
  359. def insync?(current)
  360. if provider.respond_to?(:groups_insync?)
  361. return provider.groups_insync?(current, @should)
  362. end
  363.  
  364. super(current)
  365. end
  366. end
  367.  
  368. newparam(:name) do
  369. desc "The user name. While naming limitations vary by operating system,
  370. it is advisable to restrict names to the lowest common denominator,
  371. which is a maximum of 8 characters beginning with a letter.
  372.  
  373. Note that Puppet considers user names to be case-sensitive, regardless
  374. of the platform's own rules; be sure to always use the same case when
  375. referring to a given user."
  376. isnamevar
  377. end
  378.  
  379. newparam(:membership) do
  380. desc "If `minimum` is specified, Puppet will ensure that the user is a
  381. member of all specified groups, but will not remove any other groups
  382. that the user is a part of.
  383.  
  384. If `inclusive` is specified, Puppet will ensure that the user is a
  385. member of **only** specified groups.
  386.  
  387. Defaults to `minimum`."
  388.  
  389. newvalues(:inclusive, :minimum)
  390.  
  391. defaultto :minimum
  392. end
  393.  
  394. newparam(:system, :boolean => true, :parent => Puppet::Parameter::Boolean) do
  395. desc "Whether the user is a system user, according to the OS's criteria;
  396. on most platforms, a UID less than or equal to 500 indicates a system
  397. user. This parameter is only used when the resource is created and will
  398. not affect the UID when the user is present. Defaults to `false`."
  399.  
  400. defaultto false
  401. end
  402.  
  403. newparam(:allowdupe, :boolean => true, :parent => Puppet::Parameter::Boolean) do
  404. desc "Whether to allow duplicate UIDs. Defaults to `false`."
  405.  
  406. defaultto false
  407. end
  408.  
  409. newparam(:managehome, :boolean => true, :parent => Puppet::Parameter::Boolean) do
  410. desc "Whether to manage the home directory when Puppet creates or removes the user.
  411. This creates the home directory if Puppet also creates the user account, and deletes the
  412. home directory if Puppet also removes the user account. Defaults to `false`.
  413.  
  414. This parameter has no effect unless Puppet is also creating or removing the user in the
  415. resource at the same time. For instance, Puppet creates a home directory for a managed
  416. user if `ensure => present` and the user does not exist at the time of the Puppet run.
  417. If the home directory is then deleted manually, Puppet will not recreate it on the next
  418. run."
  419.  
  420. defaultto false
  421.  
  422. validate do |val|
  423. if munge(val)
  424. raise ArgumentError, _("User provider %{name} can not manage home directories") % { name: provider.class.name } if provider and not provider.class.manages_homedir?
  425. end
  426. end
  427. end
  428.  
  429. newproperty(:expiry, :required_features => :manages_expiry) do
  430. desc "The expiry date for this user. Must be provided in
  431. a zero-padded YYYY-MM-DD format --- e.g. 2010-02-19.
  432. If you want to ensure the user account never expires,
  433. you can pass the special value `absent`."
  434.  
  435. newvalues :absent
  436. newvalues /^\d{4}-\d{2}-\d{2}$/
  437.  
  438. validate do |value|
  439. if value.intern != :absent and value !~ /^\d{4}-\d{2}-\d{2}$/
  440. #TRANSLATORS YYYY-MM-DD represents a date with a four-digit year, a two-digit month, and a two-digit day,
  441. #TRANSLATORS separated by dashes.
  442. raise ArgumentError, _("Expiry dates must be YYYY-MM-DD or the string \"absent\"")
  443. end
  444. end
  445. end
  446.  
  447. # Autorequire the group, if it's around
  448. autorequire(:group) do
  449. autos = []
  450.  
  451. if obj = @parameters[:gid] and groups = obj.shouldorig
  452. groups = groups.collect { |group|
  453. if group =~ /^\d+$/
  454. Integer(group)
  455. else
  456. group
  457. end
  458. }
  459. groups.each { |group|
  460. case group
  461. when Integer
  462. if resource = catalog.resources.find { |r| r.is_a?(Puppet::Type.type(:group)) and r.should(:gid) == group }
  463. autos << resource
  464. end
  465. else
  466. autos << group
  467. end
  468. }
  469. end
  470.  
  471. if obj = @parameters[:groups] and groups = obj.should
  472. autos += groups.split(",")
  473. end
  474.  
  475. autos
  476. end
  477.  
  478. # This method has been exposed for puppet to manage users and groups of
  479. # files in its settings and should not be considered available outside of
  480. # puppet.
  481. #
  482. # (see Puppet::Settings#service_user_available?)
  483. #
  484. # @return [Boolean] if the user exists on the system
  485. # @api private
  486. def exists?
  487. provider.exists?
  488. end
  489.  
  490. def retrieve
  491. absent = false
  492. properties.inject({}) { |prophash, property|
  493. current_value = :absent
  494.  
  495. if absent
  496. prophash[property] = :absent
  497. else
  498. current_value = property.retrieve
  499. prophash[property] = current_value
  500. end
  501.  
  502. if property.name == :ensure and current_value == :absent
  503. absent = true
  504. end
  505. prophash
  506. }
  507. end
  508.  
  509. newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
  510. desc "The roles the user has. Multiple roles should be
  511. specified as an array."
  512.  
  513. def membership
  514. :role_membership
  515. end
  516.  
  517. validate do |value|
  518. if value =~ /^\d+$/
  519. raise ArgumentError, _("Role names must be provided, not numbers")
  520. end
  521. raise ArgumentError, _("Role names must be provided as an array, not a comma-separated list") if value.include?(",")
  522. end
  523. end
  524.  
  525. #autorequire the roles that the user has
  526. autorequire(:user) do
  527. reqs = []
  528.  
  529. if roles_property = @parameters[:roles] and roles = roles_property.should
  530. reqs += roles.split(',')
  531. end
  532.  
  533. reqs
  534. end
  535.  
  536. newparam(:role_membership) do
  537. desc "Whether specified roles should be considered the **complete list**
  538. (`inclusive`) or the **minimum list** (`minimum`) of roles the user
  539. has. Defaults to `minimum`."
  540.  
  541. newvalues(:inclusive, :minimum)
  542.  
  543. defaultto :minimum
  544. end
  545.  
  546. newproperty(:auths, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
  547. desc "The auths the user has. Multiple auths should be
  548. specified as an array."
  549.  
  550. def membership
  551. :auth_membership
  552. end
  553.  
  554. validate do |value|
  555. if value =~ /^\d+$/
  556. raise ArgumentError, _("Auth names must be provided, not numbers")
  557. end
  558. raise ArgumentError, _("Auth names must be provided as an array, not a comma-separated list") if value.include?(",")
  559. end
  560. end
  561.  
  562. newparam(:auth_membership) do
  563. desc "Whether specified auths should be considered the **complete list**
  564. (`inclusive`) or the **minimum list** (`minimum`) of auths the user
  565. has. Defaults to `minimum`."
  566.  
  567. newvalues(:inclusive, :minimum)
  568.  
  569. defaultto :minimum
  570. end
  571.  
  572. newproperty(:profiles, :parent => Puppet::Property::OrderedList, :required_features => :manages_solaris_rbac) do
  573. desc "The profiles the user has. Multiple profiles should be
  574. specified as an array."
  575.  
  576. def membership
  577. :profile_membership
  578. end
  579.  
  580. validate do |value|
  581. if value =~ /^\d+$/
  582. raise ArgumentError, _("Profile names must be provided, not numbers")
  583. end
  584. raise ArgumentError, _("Profile names must be provided as an array, not a comma-separated list") if value.include?(",")
  585. end
  586. end
  587.  
  588. newparam(:profile_membership) do
  589. desc "Whether specified roles should be treated as the **complete list**
  590. (`inclusive`) or the **minimum list** (`minimum`) of roles
  591. of which the user is a member. Defaults to `minimum`."
  592.  
  593. newvalues(:inclusive, :minimum)
  594.  
  595. defaultto :minimum
  596. end
  597.  
  598. newproperty(:keys, :parent => Puppet::Property::KeyValue, :required_features => :manages_solaris_rbac) do
  599. desc "Specify user attributes in an array of key = value pairs."
  600.  
  601. def membership
  602. :key_membership
  603. end
  604.  
  605. validate do |value|
  606. raise ArgumentError, _("Key/value pairs must be separated by an =") unless value.include?("=")
  607. end
  608. end
  609.  
  610. newparam(:key_membership) do
  611. desc "Whether specified key/value pairs should be considered the
  612. **complete list** (`inclusive`) or the **minimum list** (`minimum`) of
  613. the user's attributes. Defaults to `minimum`."
  614.  
  615. newvalues(:inclusive, :minimum)
  616.  
  617. defaultto :minimum
  618. end
  619.  
  620. newproperty(:project, :required_features => :manages_solaris_rbac) do
  621. desc "The name of the project associated with a user."
  622. end
  623.  
  624. newparam(:ia_load_module, :required_features => :manages_aix_lam) do
  625. desc "The name of the I&A module to use to manage this user."
  626. end
  627.  
  628. newproperty(:attributes, :parent => Puppet::Property::KeyValue, :required_features => :manages_aix_lam) do
  629. desc "Specify AIX attributes for the user in an array of attribute = value pairs."
  630.  
  631. def membership
  632. :attribute_membership
  633. end
  634.  
  635. def delimiter
  636. " "
  637. end
  638.  
  639. validate do |value|
  640. raise ArgumentError, _("Attributes value pairs must be separated by an =") unless value.include?("=")
  641. end
  642. end
  643.  
  644. newparam(:attribute_membership) do
  645. desc "Whether specified attribute value pairs should be treated as the
  646. **complete list** (`inclusive`) or the **minimum list** (`minimum`) of
  647. attribute/value pairs for the user. Defaults to `minimum`."
  648.  
  649. newvalues(:inclusive, :minimum)
  650.  
  651. defaultto :minimum
  652. end
  653.  
  654. newproperty(:salt, :required_features => :manages_password_salt) do
  655. desc "This is the 32-byte salt used to generate the PBKDF2 password used in
  656. OS X. This field is required for managing passwords on OS X >= 10.8."
  657. end
  658.  
  659. newproperty(:iterations, :required_features => :manages_password_salt) do
  660. desc "This is the number of iterations of a chained computation of the
  661. [PBKDF2 password hash](https://en.wikipedia.org/wiki/PBKDF2). This parameter
  662. is used in OS X, and is required for managing passwords on OS X 10.8 and
  663. newer."
  664.  
  665. munge do |value|
  666. if value.is_a?(String) and value =~/^[-0-9]+$/
  667. Integer(value)
  668. else
  669. value
  670. end
  671. end
  672. end
  673.  
  674. newparam(:forcelocal, :boolean => true,
  675. :required_features => :libuser,
  676. :parent => Puppet::Parameter::Boolean) do
  677. desc "Forces the management of local accounts when accounts are also
  678. being managed by some other NSS"
  679. defaultto false
  680. end
  681.  
  682. def generate
  683. return [] if self[:purge_ssh_keys].empty?
  684. find_unmanaged_keys
  685. end
  686.  
  687. newparam(:purge_ssh_keys) do
  688. desc "Whether to purge authorized SSH keys for this user if they are not managed
  689. with the `ssh_authorized_key` resource type. Allowed values are:
  690.  
  691. * `false` (default) --- don't purge SSH keys for this user.
  692. * `true` --- look for keys in the `.ssh/authorized_keys` file in the user's
  693. home directory. Purge any keys that aren't managed as `ssh_authorized_key`
  694. resources.
  695. * An array of file paths --- look for keys in all of the files listed. Purge
  696. any keys that aren't managed as `ssh_authorized_key` resources. If any of
  697. these paths starts with `~` or `%h`, that token will be replaced with
  698. the user's home directory."
  699.  
  700. defaultto :false
  701.  
  702. # Use Symbols instead of booleans until PUP-1967 is resolved.
  703. newvalues(:true, :false)
  704.  
  705. validate do |value|
  706. if [ :true, :false ].include? value.to_s.intern
  707. return
  708. end
  709. value = [ value ] if value.is_a?(String)
  710. if value.is_a?(Array)
  711. value.each do |entry|
  712.  
  713. raise ArgumentError, _("Each entry for purge_ssh_keys must be a string, not a %{klass}") % { klass: entry.class } unless entry.is_a?(String)
  714.  
  715. valid_home = Puppet::Util.absolute_path?(entry) || entry =~ %r{^~/|^%h/}
  716. raise ArgumentError, _("Paths to keyfiles must be absolute, not %{entry}") % { entry: entry } unless valid_home
  717. end
  718. return
  719. end
  720. raise ArgumentError, _("purge_ssh_keys must be true, false, or an array of file names, not %{value}") % { value: value.inspect }
  721. end
  722.  
  723. munge do |value|
  724. # Resolve string, boolean and symbol forms of true and false to a
  725. # single representation.
  726. test_sym = value.to_s.intern
  727. value = test_sym if [:true, :false].include? test_sym
  728.  
  729. return [] if value == :false
  730. home = resource[:home]
  731. if value == :true and not home
  732. raise ArgumentError, _("purge_ssh_keys can only be true for users with a defined home directory")
  733. end
  734.  
  735. return [ "#{home}/.ssh/authorized_keys" ] if value == :true
  736. # value is an array - munge each value
  737. [ value ].flatten.map do |entry|
  738. if entry =~ /^~|^%h/ and not home
  739. raise ArgumentError, _("purge_ssh_keys value '%{value}' meta character ~ or %{home_placeholder} only allowed for users with a defined home directory") % { value: value, home_placeholder: '%h' }
  740. end
  741. entry.gsub!(/^~\//, "#{home}/")
  742. entry.gsub!(/^%h\//, "#{home}/")
  743. entry
  744. end
  745. end
  746. end
  747.  
  748. newproperty(:loginclass, :required_features => :manages_loginclass) do
  749. desc "The name of login class to which the user belongs."
  750.  
  751. validate do |value|
  752. if value =~ /^\d+$/
  753. raise ArgumentError, _("Class name must be provided.")
  754. end
  755. end
  756. end
  757.  
  758. # Generate ssh_authorized_keys resources for purging. The key files are
  759. # taken from the purge_ssh_keys parameter. The generated resources inherit
  760. # all metaparameters from the parent user resource.
  761. #
  762. # @return [Array<Puppet::Type::Ssh_authorized_key] a list of resources
  763. # representing the found keys
  764. # @see generate
  765. # @api private
  766. def find_unmanaged_keys
  767. self[:purge_ssh_keys].
  768. select { |f| File.readable?(f) }.
  769. map { |f| unknown_keys_in_file(f) }.
  770. flatten.each do |res|
  771. res[:ensure] = :absent
  772. res[:user] = self[:name]
  773. @parameters.each do |name, param|
  774. res[name] = param.value if param.metaparam?
  775. end
  776. end
  777. end
  778.  
  779. # Parse an ssh authorized keys file superficially, extract the comments
  780. # on the keys. These are considered names of possible ssh_authorized_keys
  781. # resources. Keys that are managed by the present catalog are ignored.
  782. #
  783. # @see generate
  784. # @api private
  785. # @return [Array<Puppet::Type::Ssh_authorized_key] a list of resources
  786. # representing the found keys
  787. def unknown_keys_in_file(keyfile)
  788. names = []
  789. name_index = 0
  790. # RFC 4716 specifies UTF-8 allowed in public key files per https://www.ietf.org/rfc/rfc4716.txt
  791. # the authorized_keys file may contain UTF-8 comments
  792. Puppet::FileSystem.open(keyfile, nil, 'r:UTF-8').each do |line|
  793. next unless line =~ Puppet::Type.type(:ssh_authorized_key).keyline_regex
  794. # the name is stored in the 4th capture of the regex
  795. name = $4
  796. if name.empty?
  797. key = $3.delete("\n")
  798. # If no comment is specified for this key, generate a unique internal
  799. # name. This uses the same rules as
  800. # provider/ssh_authorized_key/parsed (PUP-3357)
  801. name = "#{keyfile}:unnamed-#{name_index += 1}"
  802. end
  803. names << name
  804. Puppet.debug "#{self.ref} parsed for purging Ssh_authorized_key[#{name}]"
  805. end
  806.  
  807. names.map { |keyname|
  808. Puppet::Type.type(:ssh_authorized_key).new(
  809. :name => keyname,
  810. :target => keyfile)
  811. }.reject { |res|
  812. catalog.resource_refs.include? res.ref
  813. }
  814. end
  815. end
  816. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement