Update stdlib
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / parser / functions / fqdn_uuid.rb
1 require 'digest/sha1'
2
3 module Puppet::Parser::Functions
4   newfunction(:fqdn_uuid, :type => :rvalue, :doc => <<-END) do |args|
5
6     Creates a UUID based on a given string, assumed to be the FQDN
7
8     For example, to generate a UUID based on the FQDN of a system:
9
10     Usage:
11
12       $uuid = fqdn_uuid($::fqdn)
13
14     The generated UUID will be the same for the given hostname
15
16     The resulting UUID is returned on the form:
17
18       1d839dea-5e10-5243-88eb-e66815bd7d5c
19
20     (u.e. without any curly braces.)
21
22     The generated UUID is a version 5 UUID with the V5 DNS namespace:
23
24       6ba7b810-9dad-11d1-80b4-00c04fd430c8
25
26     This only supports a the V5 SHA-1 hash, using the DNS namespace.
27
28     Please consult http://www.ietf.org/rfc/rfc4122.txt for the details on
29     UUID generation and example implementation.
30
31     No verification is present at the moment as whether the domain name given
32     is in fact a correct fully-qualified domain name.  Therefore any arbitrary
33     string and/or alpha-numeric value can subside for a domain name.
34     EOS
35
36     END
37
38     if args.length == 0
39       raise(ArgumentError, "fqdn_uuid: No arguments given")
40     elsif args.length == 1
41       fqdn = args[0]
42     else
43       raise(ArgumentError, "fqdn_uuid: Too many arguments given (#{args.length})")
44     end
45
46     # Code lovingly taken from
47     # https://github.com/puppetlabs/marionette-collective/blob/master/lib/mcollective/ssl.rb
48
49     # This is the UUID version 5 type DNS name space which is as follows:
50     #
51     #  6ba7b810-9dad-11d1-80b4-00c04fd430c8
52     #
53     uuid_name_space_dns = [0x6b,
54       0xa7,
55       0xb8,
56       0x10,
57       0x9d,
58       0xad,
59       0x11,
60       0xd1,
61       0x80,
62       0xb4,
63       0x00,
64       0xc0,
65       0x4f,
66       0xd4,
67       0x30,
68       0xc8
69     ].map {|b| b.chr}.join
70
71     sha1 = Digest::SHA1.new
72     sha1.update(uuid_name_space_dns)
73     sha1.update(fqdn)
74
75     # first 16 bytes..
76     bytes = sha1.digest[0, 16].bytes.to_a
77
78     # version 5 adjustments
79     bytes[6] &= 0x0f
80     bytes[6] |= 0x50
81
82     # variant is DCE 1.1
83     bytes[8] &= 0x3f
84     bytes[8] |= 0x80
85
86     bytes = [4, 2, 2, 2, 6].collect do |i|
87       bytes.slice!(0, i).pack('C*').unpack('H*')
88     end
89
90     bytes.join('-')
91   end
92 end