Class: Puppet::Network::Handler::CA

Inherits:
Handler
  • Object
show all
Defined in:
lib/puppet/network/handler/ca.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = {}) ⇒ CA

Returns a new instance of CA.



61
62
63
64
65
66
# File 'lib/puppet/network/handler/ca.rb', line 61

def initialize(hash = {})
  Puppet.settings.use(:main, :ssl, :ca)
  @autosign = hash[:autosign] if hash.include? :autosign

  @ca = Puppet::SSLCertificates::CA.new(hash)
end

Instance Attribute Details

#caObject (readonly)

Returns the value of attribute ca.



11
12
13
# File 'lib/puppet/network/handler/ca.rb', line 11

def ca
  @ca
end

Instance Method Details

#autosignObject



21
22
23
24
25
26
27
# File 'lib/puppet/network/handler/ca.rb', line 21

def autosign
  if defined?(@autosign)
    @autosign
  else
    Puppet[:autosign]
  end
end

#autosign?(hostname) ⇒ Boolean

FIXME autosign? should probably accept both hostnames and IP addresses

Returns:

  • (Boolean)


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
# File 'lib/puppet/network/handler/ca.rb', line 30

def autosign?(hostname)
  # simple values are easy
  if autosign == true or autosign == false
    return autosign
  end

  # we only otherwise know how to handle files
  unless autosign =~ /^\//
    raise Puppet::Error, "Invalid autosign value #{autosign.inspect}"
  end

  unless FileTest.exists?(autosign)
    unless defined?(@@warnedonautosign)
      @@warnedonautosign = true
      Puppet.info "Autosign is enabled but #{autosign} is missing"
    end
    return false
  end
  auth = Puppet::Network::AuthStore.new
  File.open(autosign) { |f|
    f.each { |line|
      next if line =~ /^\s*#/
      next if line =~ /^\s*$/
      auth.allow(line.chomp)
    }
  }

  # for now, just cheat and pass a fake IP address to allowed?
  auth.allowed?(hostname, "127.1.1.1")
end

#getcert(csrtext, client = nil, clientip = nil) ⇒ Object

our client sends us a csr, and we either store it for later signing, or we sign it right away



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
# File 'lib/puppet/network/handler/ca.rb', line 70

def getcert(csrtext, client = nil, clientip = nil)
  csr = OpenSSL::X509::Request.new(csrtext)

  # Use the hostname from the CSR, not from the network.
  subject = csr.subject

  nameary = subject.to_a.find { |ary|
    ary[0] == "CN"
  }

  if nameary.nil?
    Puppet.err(
      "Invalid certificate request: could not retrieve server name"
    )
    return "invalid"
  end

  hostname = nameary[1]

  unless @ca
    Puppet.notice "Host #{hostname} asked for signing from non-CA master"
    return ""
  end

  # We used to save the public key, but it's basically unnecessary
  # and it mucks with the permissions requirements.
  # save_pk(hostname, csr.public_key)

  certfile = File.join(Puppet[:certdir], [hostname, "pem"].join("."))

  # first check to see if we already have a signed cert for the host
  cert, cacert = ca.getclientcert(hostname)
  if cert and cacert
    Puppet.info "Retrieving existing certificate for #{hostname}"
    unless csr.public_key.to_s == cert.public_key.to_s
      raise Puppet::Error, "Certificate request does not match existing certificate; run 'puppetca --clean #{hostname}'."
    end
    return [cert.to_pem, cacert.to_pem]
  elsif @ca
    if self.autosign?(hostname) or client.nil?
      Puppet.info "Signing certificate for CA server" if client.nil?
      # okay, we don't have a signed cert
      # if we're a CA and autosign is turned on, then go ahead and sign
      # the csr and return the results
      Puppet.info "Signing certificate for #{hostname}"
      cert, cacert = @ca.sign(csr)
      #Puppet.info "Cert: #{cert.class}; Cacert: #{cacert.class}"
      return [cert.to_pem, cacert.to_pem]
    else # just write out the csr for later signing
      if @ca.getclientcsr(hostname)
        Puppet.info "Not replacing existing request from #{hostname}"
      else
        Puppet.notice "Host #{hostname} has a waiting certificate request"
        @ca.storeclientcsr(csr)
      end
      return ["", ""]
    end
  else
    raise "huh?"
  end
end