Class: MCollective::Security::Psk

Inherits:
Base
  • Object
show all
Defined in:
lib/mcollective/security/psk.rb

Overview

Impliments message authentication using digests and shared keys

You should configure a psk in the configuration file and all requests will be validated for authenticity with this.

Serialization uses Marshal, this is the default security module that is supported out of the box.

Validation is as default and is provided by MCollective::Security::Base

You can configure the caller id being created, this can adjust how you create authorization plugins. For example you can use a unix group instead of uid to do authorization.

Instance Attribute Summary

Attributes inherited from Base

#initiated_by, #stats

Instance Method Summary collapse

Methods inherited from Base

#create_reply, #create_request, inherited, #initialize, #should_process_msg?, #valid_callerid?, #validate_filter?

Constructor Details

This class inherits a constructor from MCollective::Security::Base

Instance Method Details

#calleridObject



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
# File 'lib/mcollective/security/psk.rb', line 72

def callerid
  if @config.pluginconf.include?("psk.callertype")
    callertype = @config.pluginconf["psk.callertype"].to_sym if @config.pluginconf.include?("psk.callertype")
  else
    callertype = :uid
  end

  case callertype
    when :gid
      id  = "gid=#{Process.gid}"

    when :group
      raise "Cannot use the 'group' callertype for the PSK security plugin on the Windows platform" if Util.windows?

      id = "group=#{Etc.getgrgid(Process.gid).name}"

    when :user
      id = "user=#{Etc.getlogin}"

    when :identity
      id = "identity=#{@config.identity}"

    else
      id ="uid=#{Process.uid}"
  end

  Log.debug("Setting callerid to #{id} based on callertype=#{callertype}")

  id
end

#decodemsg(msg) ⇒ Object

Decodes a message by unserializing all the bits etc, it also validates it as valid using the psk etc



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/mcollective/security/psk.rb', line 21

def decodemsg(msg)
  body = Marshal.load(msg.payload)

  should_process_msg?(msg, body[:requestid])

  if validrequest?(body)
    body[:body] = Marshal.load(body[:body])
    return body
  else
    nil
  end
end

#encodereply(sender, msg, requestid, requestcallerid = nil) ⇒ Object

Encodes a reply



35
36
37
38
39
40
41
42
43
# File 'lib/mcollective/security/psk.rb', line 35

def encodereply(sender, msg, requestid, requestcallerid=nil)
  serialized  = Marshal.dump(msg)
  digest = makehash(serialized)

  req = create_reply(requestid, sender, serialized)
  req[:hash] = digest

  Marshal.dump(req)
end

#encoderequest(sender, msg, requestid, filter, target_agent, target_collective, ttl = 60) ⇒ Object

Encodes a request msg



46
47
48
49
50
51
52
53
54
# File 'lib/mcollective/security/psk.rb', line 46

def encoderequest(sender, msg, requestid, filter, target_agent, target_collective, ttl=60)
  serialized = Marshal.dump(msg)
  digest = makehash(serialized)

  req = create_request(requestid, filter, serialized, @initiated_by, target_agent, target_collective, ttl)
  req[:hash] = digest

  Marshal.dump(req)
end

#validrequest?(req) ⇒ Boolean

Checks the md5 hash in the request body against our psk, the request sent for validation should not have been deserialized already

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/mcollective/security/psk.rb', line 58

def validrequest?(req)
  digest = makehash(req[:body])

  if digest == req[:hash]
    @stats.validated

    return true
  else
    @stats.unvalidated

    raise(SecurityValidationFailed, "Received an invalid signature in message")
  end
end