Class: Acmesmith::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/acmesmith/client.rb

Instance Method Summary collapse

Constructor Details

#initialize(config: nil) ⇒ Client

Returns a new instance of Client.



10
11
12
# File 'lib/acmesmith/client.rb', line 10

def initialize(config: nil)
  @config ||= config
end

Instance Method Details

#add_san(name, *add_sans) ⇒ Object



148
149
150
151
152
153
154
# File 'lib/acmesmith/client.rb', line 148

def add_san(name, *add_sans)
  puts "=> reissuing #{name.inspect} with new SANs #{add_sans.join(?,)}"
  cert = load_certificate_from_storage(name)
  sans = cert.sans + add_sans
  puts " * SANs will be: #{sans.join(?,)}"
  order_with_private_key(cert.name, *sans, private_key: regenerate_private_key(cert.public_key))
end

#authorize(*identifiers) ⇒ Object

Raises:

  • (NotImplementedError)


29
30
31
# File 'lib/acmesmith/client.rb', line 29

def authorize(*identifiers)
  raise NotImplementedError, "Domain authorization in advance is still not available in acme-client (v2). Required authorizations will be performed when ordering certificates"
end

#autorenew(days: 30, remaining_life: nil, names: nil) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/acmesmith/client.rb', line 125

def autorenew(days: 30, remaining_life: nil, names: nil)
  (names || storage.list_certificates).each do |cn|
    puts "=> #{cn}"
    cert = load_certificate_from_storage(cn)

    not_after = cert.certificate.not_after.utc

    lifetime = cert.certificate.not_after.utc - cert.certificate.not_before.utc
    remaining = cert.certificate.not_after.utc - Time.now.utc
    ratio = Rational(remaining,lifetime)

    has_to_renew = false
    has_to_renew ||= days && remaining < (days.to_i * 86400)
    has_to_renew ||= remaining_life && ratio < remaining_life

    puts "   Not valid after: #{not_after} (lifetime=#{format_duration(lifetime+1)}, remaining=#{format_duration(remaining)}, #{"%0.2f" % (ratio.to_f*100)}%)"
    next unless has_to_renew

    puts " * Renewing: #{cert.name.inspect}, SANs=#{cert.sans.join(',')}"
    order_with_private_key(cert.name, *cert.sans, private_key: regenerate_private_key(cert.public_key))
  end
end

#certificate_versions(name) ⇒ Object



48
49
50
# File 'lib/acmesmith/client.rb', line 48

def certificate_versions(name)
  storage.list_certificate_versions(name).sort
end

#certificates_listObject



52
53
54
# File 'lib/acmesmith/client.rb', line 52

def certificates_list
  storage.list_certificates.sort
end

#current(name) ⇒ Object



56
57
58
# File 'lib/acmesmith/client.rb', line 56

def current(name)
  storage.get_current_certificate_version(name)
end

#execute_post_issue_hooks(certificate) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/acmesmith/client.rb', line 38

def execute_post_issue_hooks(certificate)
  hooks = config.post_issuing_hooks(certificate.name)
  return if hooks.empty?
  puts "=> Executing post issuing hooks for CN=#{certificate.name}"
  hooks.each do |hook|
    hook.run(certificate: certificate)
  end
  puts
end

#get_certificate(name, version: 'current', type: 'text') ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/acmesmith/client.rb', line 60

def get_certificate(name, version: 'current', type: 'text')
  cert = storage.get_certificate(name, version: version)

  certs = []
  case type
  when 'text'
    certs << cert.certificate.to_text
    certs << cert.certificate.to_pem
  when 'certificate'
    certs << cert.certificate.to_pem
  when 'chain'
    certs << cert.chain
  when 'fullchain'
    certs << cert.fullchain
  end

  certs
end

#get_private_key(name, version: 'current') ⇒ Object



93
94
95
96
97
98
# File 'lib/acmesmith/client.rb', line 93

def get_private_key(name, version: 'current')
  cert = storage.get_certificate(name, version: version)
  cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase

  cert.private_key.to_pem
end

#new_account(contact, tos_agreed: true) ⇒ Object



14
15
16
17
18
19
20
21
22
# File 'lib/acmesmith/client.rb', line 14

def (contact, tos_agreed: true)
  key = AccountKey.generate
  acme = Acme::Client.new(private_key: key.private_key, directory: config.directory, connection_options: config.connection_options, bad_nonce_retry: config.bad_nonce_retry)
  acme.(contact: contact, terms_of_service_agreed: tos_agreed)

  storage.(key, )

  key
end

#order(*identifiers, key_type: 'rsa', rsa_key_size: 2048, elliptic_curve: 'prime256v1', not_before: nil, not_after: nil) ⇒ Object



24
25
26
27
# File 'lib/acmesmith/client.rb', line 24

def order(*identifiers, key_type: 'rsa', rsa_key_size: 2048, elliptic_curve: 'prime256v1', not_before: nil, not_after: nil)
  private_key = generate_private_key(key_type: key_type, rsa_key_size: rsa_key_size, elliptic_curve: elliptic_curve)
  order_with_private_key(*identifiers, private_key: private_key, not_before: not_before, not_after: not_after)
end

#post_issue_hooks(name) ⇒ Object



33
34
35
36
# File 'lib/acmesmith/client.rb', line 33

def post_issue_hooks(name)
  cert = load_certificate_from_storage(name)
  execute_post_issue_hooks(cert)
end

#save(name, version: 'current', **kwargs) ⇒ Object



118
119
120
121
122
123
# File 'lib/acmesmith/client.rb', line 118

def save(name, version: 'current', **kwargs)
  cert = storage.get_certificate(name, version: version)
  cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase

  SaveCertificateService.new(cert, **kwargs).perform!
end

#save_certificate(name, version: 'current', mode: '0600', output:, type: 'fullchain') ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/acmesmith/client.rb', line 79

def save_certificate(name, version: 'current', mode: '0600', output:, type: 'fullchain')
  cert = storage.get_certificate(name, version: version)
  File.open(output, 'w', mode.to_i(8)) do |f|
    case type
    when 'certificate'
      f.puts cert.certificate.to_pem
    when 'chain'
      f.puts cert.chain
    when 'fullchain'
      f.puts cert.fullchain
    end
  end
end

#save_pkcs12(name, version: 'current', mode: '0600', output:, passphrase:) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/acmesmith/client.rb', line 108

def save_pkcs12(name, version: 'current', mode: '0600', output:, passphrase:)
  cert = storage.get_certificate(name, version: version)
  cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
  
  p12 = cert.pkcs12(passphrase)
  File.open(output, 'w', mode.to_i(8)) do |f|
    f.puts p12.to_der
  end
end

#save_private_key(name, version: 'current', mode: '0600', output:) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/acmesmith/client.rb', line 100

def save_private_key(name, version: 'current', mode: '0600', output:)
  cert = storage.get_certificate(name, version: version)
  cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
  File.open(output, 'w', mode.to_i(8)) do |f|
    f.puts(cert.private_key)
  end
end