Ensure _scrub_checklist_input honors indices order (#9943)

This fixes a bug where, when a user requests a cert interactively, the
CSR's SANs are not listed in the order that the user has in mind. This
is because, during the input validation, the _scrub_checklist_input
method does not produce a list of tags (which represents the domain
names the user has requested a cert for) in the order of in the given
indices. As a result, the CN of the resulting cert, as well as the
directory name used to store the certs, may not always be what the user
has expected, which should be the first item chosen from the interactive
prompt.
This commit is contained in:
Lukhnos Liu
2024-05-21 12:59:46 -04:00
parent 443ec2200f
commit 6c422774d5
4 changed files with 27 additions and 3 deletions

View File

@@ -166,6 +166,7 @@ Authors
* [Luca Ebach](https://github.com/lucebac)
* [Luca Olivetti](https://github.com/olivluca)
* [Luke Rogers](https://github.com/lukeroge)
* [Lukhnos Liu](https://github.com/lukhnos)
* [Maarten](https://github.com/mrtndwrd)
* [Mads Jensen](https://github.com/atombrella)
* [Maikel Martens](https://github.com/krukas)

View File

@@ -15,7 +15,10 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
### Fixed
*
* Fixed a bug in Certbot where a CSR's SANs did not always follow the order of
the domain names that the user requested interactively. In some cases, the
resulting cert's common name might seem picked up randomly from the SANs
when it should be the first item the user had in mind.
More details about these changes can be found on our GitHub repo.

View File

@@ -328,8 +328,9 @@ class FileDisplay:
except ValueError:
return []
# Remove duplicates
indices_int = list(set(indices_int))
# Remove duplicates. dict is used instead of set, since dict perserves
# insertion order as of Python 3.7
indices_int = list(dict.fromkeys(indices_int).keys())
# Check all input is within range
for index in indices_int:

View File

@@ -194,6 +194,25 @@ class FileOutputDisplayTest(unittest.TestCase):
self.displayer._scrub_checklist_input(list_, TAGS))
assert set_tags == exp[i]
def test_scrub_checklist_maintain_indices_order(self):
# pylint: disable=protected-access
source_tags = ["T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8", "T9"]
indices = [
["4", "9"],
["9", "4"],
["4", "9", "4"],
["9", "4", "9"],
]
exp = [
["T4", "T9"],
["T9", "T4"],
["T4", "T9"],
["T9", "T4"],
]
for i, list_ in enumerate(indices):
tags = self.displayer._scrub_checklist_input(list_, source_tags)
assert tags == exp[i]
@mock.patch("certbot._internal.display.util.input_with_timeout")
def test_directory_select(self, mock_input):
args = ["msg", "/var/www/html", "--flag", True]