File: elastic_user_command.rb

package info (click to toggle)
puppet-module-voxpupuli-elasticsearch 9.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,496 kB
  • sloc: ruby: 9,906; sh: 392; makefile: 4
file content (131 lines) | stat: -rw-r--r-- 3,046 bytes parent folder | download
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
# frozen_string_literal: true

# Parent provider for Elasticsearch Shield/X-Pack file-based user management
# tools.
class Puppet::Provider::ElasticUserCommand < Puppet::Provider
  attr_accessor :homedir

  # Elasticsearch's home directory.
  #
  # @return String
  def self.homedir
    @homedir ||= case Facter.value('osfamily')
                 when 'OpenBSD'
                   '/usr/local/elasticsearch'
                 else
                   '/usr/share/elasticsearch'
                 end
  end

  # Run the user management command with specified tool arguments.
  def self.command_with_path(args, configdir = nil)
    options = {
      combine: true,
      custom_environment: {
        'ES_PATH_CONF' => configdir || '/etc/elasticsearch'
      },
      failonfail: true
    }

    execute(
      [command(:users_cli)] + (args.is_a?(Array) ? args : [args]),
      options
    )
  end

  # Gather local file-based users into an array of Hash objects.
  def self.fetch_users
    begin
      output = command_with_path('list')
    rescue Puppet::ExecutionFailure => e
      debug("#fetch_users had an error: #{e.inspect}")
      return nil
    end

    debug("Raw command output: #{output}")
    matching_lines = output.split("\n").select do |u|
      # Keep only expected "user : role1,role2" formatted lines
      u[%r{^[^:]+:\s+\S+$}]
    end

    users = matching_lines.map do |u|
      # Break into ["user ", " role1,role2"]
      u.split(':').first.strip
    end

    users.map do |user|
      {
        name: user,
        ensure: :present,
        provider: name
      }
    end
  end

  # Fetch an array of provider objects from the the list of local users.
  def self.instances
    fetch_users.map do |user|
      new user
    end
  end

  # Generic prefetch boilerplate.
  def self.prefetch(resources)
    instances.each do |prov|
      if (resource = resources[prov.name])
        resource.provider = prov
      end
    end
  end

  def initialize(value = {})
    super(value)
    @property_flush = {}
  end

  # Enforce the desired state for this user on-disk.
  def flush
    arguments = []

    case @property_flush[:ensure]
    when :absent
      arguments << 'userdel'
      arguments << resource[:name]
    else
      arguments << 'useradd'
      arguments << resource[:name]
      arguments << '-p' << resource[:password]
    end

    self.class.command_with_path(arguments, resource[:configdir])
    @property_hash = self.class.fetch_users.find do |u|
      u[:name] == resource[:name]
    end
  end

  # Set this provider's `:ensure` property to `:present`.
  def create
    @property_flush[:ensure] = :present
  end

  def exists?
    @property_hash[:ensure] == :present
  end

  # Set this provider's `:ensure` property to `:absent`.
  def destroy
    @property_flush[:ensure] = :absent
  end

  # Manually set this user's password.
  def passwd
    self.class.command_with_path(
      [
        'passwd',
        resource[:name],
        '-p', resource[:password]
      ],
      resource[:configdir]
    )
  end
end