Class: Varanus::SSL::CSR

Inherits:
Object
  • Object
show all
Defined in:
lib/varanus/ssl/csr.rb

Overview

Wrapper class around a OpenSSL::X509::Request Provides helper functions to make reading information from the CSR easier

Constant Summary collapse

DEFAULT_KEY_SIZE =

Key size used when calling generate

4096

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(csr) ⇒ CSR

Returns a new instance of CSR.

Parameters:

  • csr (String, OpenSSL::X509::Request)


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

def initialize csr
  if csr.is_a? OpenSSL::X509::Request
    @request = csr
    @text = csr.to_s
  else
    @text = csr.to_s
    @request = OpenSSL::X509::Request.new @text
  end

  raise 'Improperly signed CSR' unless @request.verify @request.public_key

  cn_ref = @request.subject.to_a.find { |a| a[0] == 'CN' }
  @cn = cn_ref && cn_ref[1].downcase

  _parse_sans

  # If we have no CN or SAN, raise an error
  raise 'CSR must have a CN and/or subjectAltName' if @cn.nil? && @sans.empty?
end

Instance Attribute Details

#cnString (readonly)

Common Name (CN) for cert.

Returns:

  • (String)


53
54
55
# File 'lib/varanus/ssl/csr.rb', line 53

def cn
  @cn
end

#requestOpenSSL::X509::Request (readonly)

OpenSSL::X509::Request representation of CSR

Returns:

  • (OpenSSL::X509::Request)


57
58
59
# File 'lib/varanus/ssl/csr.rb', line 57

def request
  @request
end

Class Method Details

.generate(names, key = nil, subject = {}) ⇒ Array(OpenSSL::PKey::PKey, Varanus::SSL::CSR)

Generate a CSR

Parameters:

  • names (Array<String>)

    List of DNS names. The first one will be the CN

  • key (OpenSSL::PKey::RSA, OpenSSL::PKey::DSA, nil) (defaults to: nil)

    Secret key for the cert. A DSA key will be generated if nil is passed in.

  • subject (Hash) (defaults to: {})

    Options for the subject of the cert. By default only CN will be set

Returns:

  • (Array(OpenSSL::PKey::PKey, Varanus::SSL::CSR))

    The private key for the cert and CSR

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/varanus/ssl/csr.rb', line 17

def self.generate names, key = nil, subject = {}
  raise ArgumentError, 'names cannot be empty' if names.empty?

  subject = subject.dup
  subject['CN'] = names.first

  key ||= OpenSSL::PKey::DSA.new(DEFAULT_KEY_SIZE)

  request = OpenSSL::X509::Request.new
  request.version = 0
  request.subject = OpenSSL::X509::Name.parse subject.map { |k, v| "/#{k}=#{v}" }.join
  request.add_attribute names_to_san_attribute(names)
  if key.is_a? OpenSSL::PKey::EC
    request.public_key = key
  else
    request.public_key = key.public_key
  end

  request.sign(key, OpenSSL::Digest.new('SHA256'))

  [key, new(request)]
end

.names_to_san_attribute(names) ⇒ Object

:nodoc: Create a Subject Alternate Names attribute from an Array of dns names



42
43
44
45
46
47
48
49
# File 'lib/varanus/ssl/csr.rb', line 42

def self.names_to_san_attribute names
  ef = OpenSSL::X509::ExtensionFactory.new
  name_str = names.map { |n| "DNS:#{n}" }.join(', ')
  ext = ef.create_extension('subjectAltName', name_str, false)
  seq = OpenSSL::ASN1::Sequence([ext])
  ext_req = OpenSSL::ASN1::Set([seq])
  OpenSSL::X509::Attribute.new('extReq', ext_req)
end

Instance Method Details

#all_namesArray<String>

Unique list of all DNS names for cert (CN and subject alt names)

Returns:

  • (Array<String>)


82
83
84
# File 'lib/varanus/ssl/csr.rb', line 82

def all_names
  ([@cn] + @sans).compact.uniq
end

#key_sizeInteger

Key size for the cert

Returns:

  • (Integer)


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/varanus/ssl/csr.rb', line 88

def key_size
  case @request.public_key
  when OpenSSL::PKey::RSA
    @request.public_key.n.num_bytes * 8
  when OpenSSL::PKey::DSA
    @request.public_key.p.num_bytes * 8
  when OpenSSL::PKey::EC
    @request.public_key.group.degree
  else
    raise "Unknown public key type: #{@request.public_key.class}"
  end
end

#subject_alt_namesArray<String>

DNS subject alt names

Returns:

  • (Array<String>)


108
109
110
# File 'lib/varanus/ssl/csr.rb', line 108

def subject_alt_names
  @sans
end

#to_sObject

PEM format for cert



102
103
104
# File 'lib/varanus/ssl/csr.rb', line 102

def to_s
  @text
end