Class: Hiera::Backend::Eyaml::Encryptors::Pkcs7

Inherits:
Hiera::Backend::Eyaml::Encryptor show all
Defined in:
lib/hiera/backend/eyaml/encryptors/pkcs7.rb

Class Method Summary collapse

Methods inherited from Hiera::Backend::Eyaml::Encryptor

debug, decode, encode, find, format_message, hiera?, info, option, plugin_classname, register, trace, warn

Class Method Details

.create_keysObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 64

def self.create_keys
  # Do equivalent of:
  # openssl req -x509 -nodes -newkey rsa:2048 -keyout privatekey.pem -out publickey.pem -batch

  public_key = option :public_key
  private_key = option :private_key
  keysize = option :keysize

  key = OpenSSL::PKey::RSA.new(keysize)
  EncryptHelper.ensure_key_dir_exists private_key
  EncryptHelper.write_important_file filename: private_key, content: key.to_pem, mode: 0o600

  cert = OpenSSL::X509::Certificate.new
  # In JRuby implementation of openssl, not_before and not_after
  # are required to sign cert with key and digest. Signing the
  # certificate is only required for Ruby 2.7 to call cert.to_pem.
  cert.not_before = Time.now
  cert.not_after = if 1.size == 8 # 64bit
                     Time.now + (50 * 365 * 24 * 60 * 60)
                   else # 32bit
                     Time.at(0x7fffffff)
                   end
  cert.public_key = key.public_key
  cert.sign key, OpenSSL::Digest.new('SHA256')

  EncryptHelper.ensure_key_dir_exists public_key
  EncryptHelper.write_important_file filename: public_key, content: cert.to_pem
  LoggingHelper.info 'Keys created OK'
end

.decrypt(ciphertext) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 48

def self.decrypt(ciphertext)
  LoggingHelper.trace 'PKCS7 decrypt'

  private_key_pem = load_private_key_pem
  private_key_rsa = OpenSSL::PKey::RSA.new(private_key_pem)

  pkcs7 = OpenSSL::PKCS7.new(ciphertext)

  public_key_x509 = OpenSSL::X509::Certificate.new
  public_key_x509.serial = pkcs7.recipients[0].serial
  public_key_x509.issuer = pkcs7.recipients[0].issuer
  public_key_x509.public_key = private_key_rsa.public_key

  pkcs7.decrypt(private_key_rsa, public_key_x509)
end

.encrypt(plaintext) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 30

def self.encrypt(plaintext)
  LoggingHelper.trace 'PKCS7 encrypt'

  public_key_pem = load_public_key_pem
  if public_key_pem.include? 'BEGIN CERTIFICATE'
    public_key_x509 = OpenSSL::X509::Certificate.new(public_key_pem)
  elsif public_key_pem.include? 'BEGIN PUBLIC KEY'
    public_key_rsa = OpenSSL::PKey::RSA.new(public_key_pem)
    public_key_x509 = OpenSSL::X509::Certificate.new
    public_key_x509.public_key = public_key_rsa.public_key
  else
    raise StandardError, "file #{public_key_pem} cannot be used to encrypt - invalid public key format"
  end

  cipher = OpenSSL::Cipher.new('aes-256-cbc')
  OpenSSL::PKCS7.encrypt([public_key_x509], plaintext, cipher, OpenSSL::PKCS7::BINARY).to_der
end

.load_ANY_key_pem(optname_key, optname_env_var) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 94

def self.load_ANY_key_pem(optname_key, optname_env_var)
  opt_key = option(optname_key.to_sym)
  opt_key_env_var = option(optname_env_var.to_sym)

  if opt_key and opt_key_env_var
    warn "both #{optname_key} and #{optname_env_var} specified, using #{optname_env_var}"
  end

  if opt_key_env_var
    raise StandardError, "env #{opt_key_env_var} is not set" unless ENV[opt_key_env_var]

    opt_key_pem = ENV.fetch(opt_key_env_var, nil)
  elsif opt_key
    raise StandardError, "file #{opt_key} does not exist" unless File.exist? opt_key

    opt_key_pem = File.read opt_key
  else
    raise StandardError, "pkcs7_#{optname_key} is not defined" unless opt_key or opt_key_env_var
  end

  opt_key_pem
end

.load_private_key_pemObject



121
122
123
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 121

def self.load_private_key_pem
  load_ANY_key_pem('private_key', 'private_key_env_var')
end

.load_public_key_pemObject



117
118
119
# File 'lib/hiera/backend/eyaml/encryptors/pkcs7.rb', line 117

def self.load_public_key_pem
  load_ANY_key_pem('public_key', 'public_key_env_var')
end