summaryrefslogtreecommitdiff
path: root/lib/ohai/plugins/shard.rb
blob: 259bdc6ba0c56beceba4a480252dc9699fa6684e (plain)
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
#
# Author:: Phil Dibowitz <phil@ipom.com>
# Copyright:: Copyright (c) 2016 Facebook, 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.
#

Ohai.plugin(:ShardSeed) do
  depends "hostname", "dmi", "machine_id", "machinename", "fips", "hardware", "kernel"
  provides "shard_seed"

  def get_dmi_property(dmi, thing)
    %w{system base_board chassis}.each do |section|
      if dmi[section] && dmi[section][thing] && !dmi[section][thing].strip.empty?
        return dmi[section][thing]
      end
    end
    Ohai::Log.error("shard_seed: Failed to get dmi property #{thing}: is dmidecode installed?")
    raise "Failed to generate shard_seed"
  end

  def default_sources
    case collect_os
    when "linux", "darwin", "windows"
      %i{machinename serial uuid}
    else
      [:machinename]
    end
  end

  def default_digest_algorithm
    if fips && fips["kernel"]["enabled"]
      # Even though it is being used safely, FIPS-mode will still blow up on
      # any use of MD5 so default to SHA2 instead.
      "sha256"
    else
      "md5"
    end
  end

  def digest_algorithm
    case Ohai.config[:plugin][:shard_seed][:digest_algorithm] || default_digest_algorithm
    when "md5"
      require "digest/md5"
      Digest::MD5
    when "sha256"
      require "openssl/digest"
      OpenSSL::Digest::SHA256
    end
  end

  # Common sources go here. Put sources that need to be different per-platform
  # under their collect_data block.
  def create_seed(&block)
    sources = Ohai.config[:plugin][:shard_seed][:sources] || default_sources
    data = ""
    sources.each do |src|
      data << case src
              when :fqdn
                fqdn
              when :hostname
                hostname
              when :machine_id
                machine_id
              when :machinename
                machinename
              else
                yield(src)
              end
    end
    if data.empty?
      Ohai::Log.error("shard_seed: Unable to generate seed! Either ensure 'dmidecode' is installed, or use 'Ohai.config[:plugin][:shard_seed][:sources]' to set different sources.")
      raise "Failed to generate shard_seed"
    end
    shard_seed digest_algorithm.hexdigest(data)[0...7].to_i(16)
  end

  collect_data do
    create_seed do |src|
      Ohai::Log.error("shard_seed: No such source #{src}")
      raise "No such shard_seed source: #{src}"
    end
  end

  collect_data(:windows) do
    require "wmi-lite/wmi"
    wmi = WmiLite::Wmi.new

    create_seed do |src|
      case src
      when :serial
        wmi.first_of("Win32_BIOS")["SerialNumber"]
      when :os_serial
        kernel["os_info"]["serial_number"]
      when :uuid
        wmi.first_of("Win32_ComputerSystemProduct")["UUID"]
      else
        Ohai::Log.error("shard_seed: No such source #{src}")
        raise "No such shard_seed source: #{src}"
      end
    end
  end

  collect_data(:darwin) do
    create_seed do |src|
      case src
      when :serial
        hardware["serial_number"]
      when :uuid
        hardware["platform_UUID"]
      else
        Ohai::Log.error("shard_seed: No such source #{src}")
        raise "No such shard_seed source: #{src}"
      end
    end
  end

  collect_data(:linux) do
    create_seed do |src|
      case src
      when :serial
        get_dmi_property(dmi, :serial_number)
      when :uuid
        get_dmi_property(dmi, :uuid)
      else
        Ohai::Log.error("shard_seed: No such source #{src}")
        raise "No such shard_seed source: #{src}"
      end
    end
  end
end