Module: Fluent::PluginHelper::CertOption

Included in:
Server
Defined in:
lib/fluent/plugin_helper/cert_option.rb

Instance Method Summary collapse

Instance Method Details

#cert_option_cert_generation_opts_from_conf(conf) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/fluent/plugin_helper/cert_option.rb', line 80

def cert_option_cert_generation_opts_from_conf(conf)
  {
    private_key_length: conf.generate_private_key_length,
    country: conf.generate_cert_country,
    state: conf.generate_cert_state,
    locality: conf.generate_cert_locality,
    common_name: conf.generate_cert_common_name || ::Socket.gethostname,
    expiration: conf.generate_cert_expiration,
    digest: conf.generate_cert_digest,
  }
end

#cert_option_certificates_from_file(path) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/fluent/plugin_helper/cert_option.rb', line 150

def cert_option_certificates_from_file(path)
  data = File.read(path)
  pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\n(?:[^-]*\n)+-+END CERTIFICATE-+\n', Regexp::MULTILINE)
  list = []
  data.scan(pattern){|match| list << OpenSSL::X509::Certificate.new(match) }
  list
end

#cert_option_create_context(version, insecure, ciphers, conf) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fluent/plugin_helper/cert_option.rb', line 24

def cert_option_create_context(version, insecure, ciphers, conf)
  cert, key, extra = cert_option_server_validate!(conf)

  ctx = OpenSSL::SSL::SSLContext.new(version)
  unless insecure
    # inject OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
    # https://bugs.ruby-lang.org/issues/9424
    ctx.set_params({})

    ctx.ciphers = ciphers
  end

  ctx.cert = cert
  ctx.key = key
  if extra && !extra.empty?
    ctx.extra_chain_cert = extra
  end

  ctx
end

#cert_option_generate_ca_pair_self_signed(generate_opts) ⇒ Object



114
115
116
117
118
119
120
121
122
# File 'lib/fluent/plugin_helper/cert_option.rb', line 114

def cert_option_generate_ca_pair_self_signed(generate_opts)
  cert, key = cert_option_generate_pair(generate_opts)

  # basicConstraints: this cert is for CA or not
  cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)]))

  cert.sign(key, generate_opts[:digest].to_s)
  return cert, key
end

#cert_option_generate_pair(opts, issuer = nil) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/fluent/plugin_helper/cert_option.rb', line 92

def cert_option_generate_pair(opts, issuer = nil)
  key = OpenSSL::PKey::RSA.generate(opts[:private_key_length])

  subject = OpenSSL::X509::Name.new
  subject.add_entry('C', opts[:country])
  subject.add_entry('ST', opts[:state])
  subject.add_entry('L', opts[:locality])
  subject.add_entry('CN', opts[:common_name])

  issuer ||= subject

  cert = OpenSSL::X509::Certificate.new
  cert.not_before = Time.at(0)
  cert.not_after = Time.now + opts[:expiration]
  cert.public_key = key
  cert.serial = 1
  cert.issuer = issuer
  cert.subject  = subject

  return cert, key
end

#cert_option_generate_server_pair_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, generate_opts) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/fluent/plugin_helper/cert_option.rb', line 124

def cert_option_generate_server_pair_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, generate_opts)
  ca_key = OpenSSL::PKey::RSA.new(File.read(ca_key_path), ca_key_passphrase)
  ca_cert = OpenSSL::X509::Certificate.new(File.read(ca_cert_path))
  cert, key = cert_option_generate_pair(generate_opts, ca_cert.subject)
  raise "BUG: certificate digest algorithm not set" unless generate_opts[:digest]

  # basicConstraints: this cert is for CA or not
  cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
  cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')

  cert.sign(ca_key, generate_opts[:digest].to_s)
  return cert, key, nil
end

#cert_option_generate_server_pair_self_signed(generate_opts) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/fluent/plugin_helper/cert_option.rb', line 138

def cert_option_generate_server_pair_self_signed(generate_opts)
  cert, key = cert_option_generate_pair(generate_opts)
  raise "BUG: certificate digest algorithm not set" unless generate_opts[:digest]

  # basicConstraints: this cert is for CA or not
  cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
  cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')

  cert.sign(key, generate_opts[:digest].to_s)
  return cert, key, nil
end

#cert_option_load(cert_path, private_key_path, private_key_passphrase) ⇒ Object



73
74
75
76
77
78
# File 'lib/fluent/plugin_helper/cert_option.rb', line 73

def cert_option_load(cert_path, private_key_path, private_key_passphrase)
  key = OpenSSL::PKey::RSA.new(File.read(private_key_path), private_key_passphrase)
  certs = cert_option_certificates_from_file(cert_path)
  cert = certs.shift
  return cert, key, certs
end

#cert_option_server_validate!(conf) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fluent/plugin_helper/cert_option.rb', line 45

def cert_option_server_validate!(conf)
  case
  when conf.cert_path
    raise Fluent::ConfigError, "private_key_path is required when cert_path is specified" unless conf.private_key_path
    log.warn "For security reason, setting private_key_passphrase is recommended when cert_path is specified" unless conf.private_key_passphrase
    cert_option_load(conf.cert_path, conf.private_key_path, conf.private_key_passphrase)

  when conf.ca_cert_path
    raise Fluent::ConfigError, "ca_private_key_path is required when ca_cert_path is specified" unless conf.ca_private_key_path
    log.warn "For security reason, setting ca_private_key_passphrase is recommended when ca_cert_path is specified" unless conf.ca_private_key_passphrase
    generate_opts = cert_option_cert_generation_opts_from_conf(conf)
    cert_option_generate_server_pair_by_ca(
      conf.ca_cert_path,
      conf.ca_private_key_path,
      conf.ca_private_key_passphrase,
      generate_opts
    )

  when conf.insecure
    log.warn "insecure TLS communication server is configured (using 'insecure' mode)"
    generate_opts = cert_option_cert_generation_opts_from_conf(conf)
    cert_option_generate_server_pair_self_signed(generate_opts)

  else
    raise Fluent::ConfigError, "no valid cert options configured. specify either 'cert_path', 'ca_cert_path' or 'insecure'"
  end
end