Skip to content

Commit

Permalink
use xor for generate_mac
Browse files Browse the repository at this point in the history
- add entropy / reduce probability of mac collisions
- makes macs more opaque / non-sequential
- SQUASH THIS
  • Loading branch information
rrotter committed Jan 21, 2025
1 parent 4368df1 commit ac397b4
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 21 deletions.
22 changes: 11 additions & 11 deletions lib/puppet/functions/generate_mac.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require 'digest'
require "digest"

# generates a deterministic pseudorandom mac address, using hostname as seed
#
Expand All @@ -12,27 +12,27 @@
#
# generated address contains
# - 3 byte fixed OUI (prefix)
# - 21 "random" bits (seeded from hostname)
# - 3 bit sequential number (index)
# - 3 "random" byte (seeded from hostname)
# - XOR with up to 3 bits (index) for additonal interfaces
Puppet::Functions.create_function(:generate_mac) do
dispatch :generate_mac do
param "String", :prefix
param "String", :hostname
param "Integer", :index
optional_param "Integer", :index
end

def generate_mac(prefix, hostname, index)
unless(index.between?(0,7))
def generate_mac(prefix, hostname, index = 0)
unless index.between?(0, 7)
raise(ArgumentError, "#{index} must be between 0 and 7, I can only generate 8 mac addresses per host!")
end

oui = prefix.downcase.gsub(/[^0-9a-z]/,'')
unless(oui =~ /^[a-f0-9][26ae][a-f0-9]{4}$/)
oui = prefix.downcase.gsub(/[^0-9a-z]/, "")
unless /^[a-f0-9][26ae][a-f0-9]{4}$/.match?(oui)
raise(ArgumentError, "invalid mac prefix!")
end

integer_id = (Digest::SHA256.hexdigest(hostname)[0,6].to_i(16) & 0xFF_FF_F8) + index
hex_id = sprintf('%06x',integer_id)
"#{oui}#{hex_id}".each_char.each_slice(2).map{|x| x.join}.join(':')
integer_id = Digest::SHA256.hexdigest(hostname)[0, 6].to_i(16) ^ index
hex_id = sprintf("%06x", integer_id)
"#{oui}#{hex_id}".each_char.each_slice(2).map { |x| x.join }.join(":")
end
end
19 changes: 9 additions & 10 deletions spec/functions/generate_mac_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,22 @@

describe "generate_mac" do
it "generates simple addresses" do
is_expected.to run.with_params('02:00:00', 'example.com', 0).and_return('02:00:00:a3:79:a0')
is_expected.to run.with_params('12-0f-00', 'example.com', 2).and_return('12:0f:00:a3:79:a2')
is_expected.to run.with_params("02:00:00", "example.com").and_return("02:00:00:a3:79:a6")
is_expected.to run.with_params("12-0f-00", "example.com", 2).and_return("12:0f:00:a3:79:a4")
end
it "fails on invalid chars" do
is_expected.to run.with_params('g2:00:00', 'example.com', 0).and_raise_error(ArgumentError)
is_expected.to run.with_params("g2:00:00", "example.com", 0).and_raise_error(ArgumentError)
end
it "correctly masks final 3 bits" do
is_expected.to run.with_params('06 12 34', 'my.host.name', 0).and_return('06:12:34:3b:d9:98')
is_expected.to run.with_params('5a.67.89', 'my.host.name', 3).and_return('5a:67:89:3b:d9:9b')
is_expected.to run.with_params('AE:BC:DE', 'my.host.name', 7).and_return('ae:bc:de:3b:d9:9f')
is_expected.to run.with_params("06 12 34", "my.host.name", 0).and_return("06:12:34:3b:d9:9a")
is_expected.to run.with_params("5a.67.89", "my.host.name", 3).and_return("5a:67:89:3b:d9:99")
is_expected.to run.with_params("AE:BC:DE", "my.host.name", 7).and_return("ae:bc:de:3b:d9:9d")
end
it "fails on non-private oui" do
is_expected.to run.with_params('03:00:00', 'example.com', 0).and_raise_error(ArgumentError)
is_expected.to run.with_params("03:00:00", "example.com", 0).and_raise_error(ArgumentError)
end
it "fails on out of range index" do
is_expected.to run.with_params('02:00:00', 'example.com', 11).and_raise_error(ArgumentError)
is_expected.to run.with_params('02:00:00', 'example.com', -1).and_raise_error(ArgumentError)
is_expected.to run.with_params("02:00:00", "example.com", 11).and_raise_error(ArgumentError)
is_expected.to run.with_params("02:00:00", "example.com", -1).and_raise_error(ArgumentError)
end
end

0 comments on commit ac397b4

Please # to comment.