Class: Puppetserver::Ca::RevokeAction

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/puppetserver/ca/revoke_action.rb

Constant Summary collapse

REQUEST_BODY =
JSON.dump({ desired_state: 'revoked' })
CERTNAME_BLACKLIST =
%w{--all --config}
SUMMARY =
'Revoke a given certificate'
<<-BANNER
Usage:
  puppetserver ca revoke [--help|--version]
  puppetserver ca revoke [--config] --certname CERTNAME[,ADDLCERTNAME]

Description:
Given one or more valid certnames, instructs the CA to revoke them over
HTTPS using the local agent's PKI

Options:
BANNER

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(logger) ⇒ RevokeAction

Returns a new instance of RevokeAction.



48
49
50
# File 'lib/puppetserver/ca/revoke_action.rb', line 48

def initialize(logger)
  @logger = logger
end

Class Method Details

.parser(parsed = {}) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/puppetserver/ca/revoke_action.rb', line 31

def self.parser(parsed = {})
  parsed['certnames'] = []
  OptionParser.new do |o|
    o.banner = BANNER
    o.on('--certname foo,bar', Array,
         'One or more comma separated certnames') do |certs|
      parsed['certnames'] += certs
    end
    o.on('--config PUPPET.CONF', 'Custom path to puppet.conf') do |conf|
      parsed['config'] = conf
    end
    o.on('--help', 'Displays this revoke specific help output') do |help|
      parsed['help'] = help
    end
  end
end

Instance Method Details

#check_result(result, certname) ⇒ Object

logs the action and returns a boolean for success/failure



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/puppetserver/ca/revoke_action.rb', line 119

def check_result(result, certname)
  case result.code
  when '200', '204'
    @logger.inform "Revoked certificate for #{certname}"
    return true
  when '404'
    @logger.err 'Error:'
    @logger.err "    Could not find certificate for #{certname}"
    return false
  else
    @logger.err 'Error:'
    @logger.err "    When revoking #{certname} received:"
    @logger.err "      code: #{result.code}"
    @logger.err "      body: #{result.body.to_s}" if result.body
    return false
  end
end

#parse(args) ⇒ Object



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
# File 'lib/puppetserver/ca/revoke_action.rb', line 52

def parse(args)
  results = {}
  parser = self.class.parser(results)

  errors = Utils.parse_with_errors(parser, args)

  results['certnames'].each do |certname|
    if CERTNAME_BLACKLIST.include?(certname)
      errors << "    Cannot manage cert named `#{certname}` from " +
                "the CLI, if needed use the HTTP API directly"
    end
  end

  if results['certnames'].empty?
    errors << '  At least one certname is required to revoke'
  end

  errors_were_handled = Utils.handle_errors(@logger, errors, parser.help)

  # if there is an exit_code then Cli will return it early, so we only
  # return an exit_code if there's an error
  exit_code = errors_were_handled ? 1 : nil

  return results, exit_code
end

#revoke_certs(certnames, settings) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/puppetserver/ca/revoke_action.rb', line 95

def revoke_certs(certnames, settings)
  client = HttpClient.new(settings[:localcacert],
                          settings[:certificate_revocation],
                          settings[:hostcrl])

  url = client.make_ca_url(settings[:ca_server],
                           settings[:ca_port],
                           'certificate_status')

  # results will be a list of trues & falses based on the success
  # of revocations
  results = client.with_connection(url) do |connection|
    certnames.map do |certname|
      url.resource_name = certname
      result = connection.put(REQUEST_BODY, url)

      check_result(result, certname)
    end
  end

  return results.all?
end

#run(args) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/puppetserver/ca/revoke_action.rb', line 78

def run(args)
  certnames = args['certnames']
  config = args['config']

  if config
    errors = FileUtilities.validate_file_paths(config)
    return 1 if Utils.handle_errors(@logger, errors)
  end

  puppet = PuppetConfig.parse(config)
  return 1 if Utils.handle_errors(@logger, puppet.errors)

  passed = revoke_certs(certnames, puppet.settings)

  return passed ? 0 : 1
end