@@ -127,31 +127,14 @@ def manage_csr_extensions(csr, new_cert)
127127 )
128128
129129 # Alternate Names
130- cn = cn_from_csr ( csr )
131- existing_sans = filter_sans ( csr_sans ( csr ) )
132- valid_alts = ( [ "DNS:#{ cn } " ] + [ *existing_sans ] ) . uniq
130+ valid_alts = build_valid_alt_names ( csr )
133131
134132 new_cert . add_extension ( ef . create_extension ( "subjectAltName" , valid_alts . join ( "," ) ) )
135133
136134 # return the updated cert and any subject alternate names added
137135 [ new_cert , valid_alts ]
138136 end
139137
140- def csr_sans ( csr )
141- raw_attributes = csr . attributes
142- return [ ] unless raw_attributes
143-
144- seq = extract_csr_attrs ( csr )
145- return [ ] unless seq
146-
147- values = extract_san_values ( seq )
148- return [ ] unless values
149-
150- values = OpenSSL ::ASN1 . decode ( values ) . value
151-
152- values . select { |v | v . tag == 2 } . map { |v | "DNS:#{ v . value } " }
153- end
154-
155138 def extract_csr_attrs ( csr )
156139 csr . attributes . select { |a | a . oid == "extReq" } . map { |a | a . value . map ( &:value ) }
157140 end
@@ -161,8 +144,9 @@ def extract_csr_sans(csr_attrs)
161144 end
162145
163146 def extract_csr_domains ( csr_sans )
164- csr_decoded_sans = OpenSSL ::ASN1 . decode ( csr_sans . first . value [ 1 ] . value )
165- csr_decoded_sans . select { |v | v . tag == 2 } . map ( &:value )
147+ subject_alt_names = csr_sans . first . value . find { |v | v . tag == 4 }
148+ csr_decoded_sans = OpenSSL ::ASN1 . decode ( subject_alt_names . value )
149+ csr_decoded_sans . value . select { |v | v . tag == 2 } . map ( &:value )
166150 end
167151
168152 def extract_san_values ( sequence )
@@ -184,13 +168,33 @@ def filter_sans(potential_sans)
184168 end
185169
186170 def cn_from_csr ( csr )
187- if csr . subject . to_s
188- cns = csr . subject . to_s . split ( "/" ) . grep ( /^CN=/ )
171+ return unless csr . subject . to_s
189172
190- return cns . first . split ( "=" ) . last if cns && !cns . empty?
191- end
173+ cns = csr . subject . to_s . split ( "/" ) . grep ( /^CN=/ )
174+
175+ cns . first . split ( "=" ) . last if cns && !cns . empty?
176+ end
177+
178+ def cn_or_first_san_from_csr ( csr )
179+ cn = cn_from_csr ( csr )
180+ return cn if cn
181+
182+ csr_attrs = extract_csr_attrs ( csr )
183+ csr_sans = extract_csr_sans ( csr_attrs )
184+ extract_csr_domains ( csr_sans ) . first
185+ end
186+
187+ def domains_from_csr ( csr )
188+ csr_attrs = extract_csr_attrs ( csr )
189+ csr_sans = extract_csr_sans ( csr_attrs )
190+ extract_csr_domains ( csr_sans )
191+ end
192192
193- csr_sans ( csr ) . first . split ( ":" ) . last
193+ def build_valid_alt_names ( csr )
194+ cn = cn_or_first_san_from_csr ( csr )
195+ csr_domains = domains_from_csr ( csr )
196+ existing_sans = filter_sans ( csr_domains ) . map { |d | "DNS:#{ d } " }
197+ ( [ "DNS:#{ cn } " ] + [ *existing_sans ] ) . uniq
194198 end
195199
196200 # Signs an ACME CSR
@@ -206,7 +210,7 @@ def sign_csr(csr, username)
206210 csr_cert . not_after = csr_cert . not_before + ( 3 * 30 * 24 * 60 * 60 )
207211
208212 # Force a subject if the cert doesn't have one
209- cert . subject = simple_subject ( cn_from_csr ( csr ) ) unless cert . subject
213+ cert . subject = simple_subject ( cn_or_first_san_from_csr ( csr ) ) unless cert . subject
210214
211215 csr_cert . subject = simple_subject ( cert . subject . to_s )
212216
0 commit comments