diff --git a/certbot-iis/LICENSE.txt b/certbot-iis/LICENSE.txt new file mode 100644 index 00000000000..02a1459be80 --- /dev/null +++ b/certbot-iis/LICENSE.txt @@ -0,0 +1,216 @@ + Copyright 2015 Electronic Frontier Foundation and others + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Incorporating code from nginxparser + Copyright 2014 Fatih Erikli + Licensed MIT + + +Text of Apache License +====================== + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +Text of MIT License +=================== +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/certbot-iis/MANIFEST.in b/certbot-iis/MANIFEST.in new file mode 100644 index 00000000000..69e5720e3fc --- /dev/null +++ b/certbot-iis/MANIFEST.in @@ -0,0 +1,5 @@ +include LICENSE.txt +include README.rst +recursive-include certbot_iis * +global-exclude __pycache__ +global-exclude *.py[cod] diff --git a/certbot-iis/README.rst b/certbot-iis/README.rst new file mode 100644 index 00000000000..e4a2adb9057 --- /dev/null +++ b/certbot-iis/README.rst @@ -0,0 +1 @@ +IIS plugin for Certbot diff --git a/certbot-iis/certbot_iis/__init__.py b/certbot-iis/certbot_iis/__init__.py new file mode 100644 index 00000000000..6e9226d816a --- /dev/null +++ b/certbot-iis/certbot_iis/__init__.py @@ -0,0 +1 @@ +"""Certbot IIS plugin.""" diff --git a/certbot-iis/certbot_iis/_internal/__init__.py b/certbot-iis/certbot_iis/_internal/__init__.py new file mode 100644 index 00000000000..8c8e519f087 --- /dev/null +++ b/certbot-iis/certbot_iis/_internal/__init__.py @@ -0,0 +1 @@ +"""Certbot IIS plugin internal implementation.""" diff --git a/certbot-iis/certbot_iis/_internal/configurator.py b/certbot-iis/certbot_iis/_internal/configurator.py new file mode 100644 index 00000000000..9735de4fdd0 --- /dev/null +++ b/certbot-iis/certbot_iis/_internal/configurator.py @@ -0,0 +1,315 @@ +# pylint: disable=too-many-lines +"""IIS Configuration""" +import logging +import re +import socket +import subprocess +import tempfile +import time +from typing import Any +from typing import Callable +from typing import Dict +from typing import Iterable +from typing import List +from typing import Mapping +from typing import Optional +from typing import Sequence +from typing import Set +from typing import Text +from typing import Tuple +from typing import Type +from typing import Union + +import OpenSSL +import pkg_resources + +from acme import challenges +from acme import crypto_util as acme_crypto_util +from certbot import achallenges +from certbot import crypto_util +from certbot import errors +from certbot import util +from certbot.compat import os +from certbot.display import util as display_util +from certbot.plugins import common +from certbot_iis._internal import constants +from certbot_iis._internal import iis_http_01 + +from cryptography.hazmat.primitives.serialization import load_pem_private_key +from cryptography.x509 import load_pem_x509_certificate +from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates +from cryptography.hazmat.primitives.serialization import NoEncryption + +NAME_RANK = 0 +START_WILDCARD_RANK = 1 +END_WILDCARD_RANK = 2 +REGEX_RANK = 3 +NO_SSL_MODIFIER = 4 + + +logger = logging.getLogger(__name__) + + +class IISConfigurator(common.Configurator): + + description = "IIS Web Server plugin" + + @classmethod + def add_parser_arguments(cls, add: Callable[..., None]) -> None: + default_server_root = _determine_default_server_root() + add("server-root", default=constants.CLI_DEFAULTS["server_root"], + help="IIS server root directory. (default: %s)" % default_server_root) + add("ctl", default=constants.CLI_DEFAULTS["ctl"], help="Path to the " + "'IIS' binary, used for 'configtest' and retrieving IIS " + "version number.") + add("sleep-seconds", default=constants.CLI_DEFAULTS["sleep_seconds"], type=int, + help="Number of seconds to wait for IIS configuration changes " + "to apply when reloading.") + + def __init__(self, *args: Any, **kwargs: Any) -> None: + """Initialize an IIS Configurator. + + :param tup version: version of IIS as a tuple (1, 4, 7) + (used mostly for unittesting) + + :param tup openssl_version: version of OpenSSL linked to IIS as a tuple (1, 4, 7) + (used mostly for unittesting) + + """ + super().__init__(*args, **kwargs) + + logger.debug("////// INIT \\\\\\") + + # Add number of outstanding challenges + self._chall_out = 0 + self.parser: None + + self.args = args + + # This is called in determine_authenticator and determine_installer + def prepare(self) -> None: + """ Verify IIS is installed """ + # if not util.exe_exists(self.conf('ctl')): + # raise errors.NoInstallationError( + # "Could not find a usable 'IIS' binary. Ensure IIS exists, " + # "the binary is executable, and your PATH is set correctly.") + + # self.parser = iis_parser.IISParser(self.conf('server-root')) + + # Entry point in main.py for installing cert + def deploy_cert(self, domain: str, cert_path: str, key_path: str, chain_path: str, + fullchain_path: str) -> None: + """Deploys certificate to specified virtual host. + + .. note:: Aborts if the vhost is missing ssl_certificate or + ssl_certificate_key. + + .. note:: This doesn't save the config files! + + :raises errors.PluginError: When unable to deploy certificate due to + a lack of directives or configuration + + :param str domain: domain to deploy certificate file + :param str cert_path: absolute path to the certificate file + :param str key_path: absolute path to the private key file + :param str chain_path: absolute path to the certificate chain file + :param str fullchain_path: absolute path to the certificate fullchain + file (cert plus chain) + + """ + + folder_path = os.path.dirname(os.path.abspath(cert_path)) + logger.debug("In deploy cert") + logger.debug("cert path :" + cert_path) + logger.debug("key path :" + key_path) + logger.debug("folder path :" + folder_path) + logger.debug("current path :" + os.getcwd()) + + pem_cert = load_pem_x509_certificate(open(cert_path,"rb").read()) + + priv_key = load_pem_private_key(open(key_path, "rb").read(), None) + + pfx = serialize_key_and_certificates(None, priv_key, pem_cert, None, NoEncryption()) + + iis_cert_name = self.args[0].iis_cert_name + + with open(folder_path + '\\' + iis_cert_name, "wb") as pfx_cert: + pfx_cert.write(pfx) + + current_path = os.getcwd() + with open(current_path + '\\iis-cert-path.txt' , "w") as cert_path: + cert_path.write(folder_path) + + + def restart(self) -> None: + """Restarts nginx server. + + :raises .errors.MisconfigurationError: If either the reload fails. + + """ + # nginx_restart(self.conf('ctl'), self.nginx_conf, self.conf('sleep-seconds')) + + + def config_test(self) -> None: + """Check the configuration of IIS for errors. + + :raises .errors.MisconfigurationError: If config_test fails + + """ + + def more_info(self) -> str: + """Human-readable string to help understand the module""" + return ( + "Configures IIS to authenticate and install HTTPS.{0}" + "Server root: {root}{0}" + "Version: {version}".format( + os.linesep, root=self.parser, + version=".".join(str(i) for i in self.version)) + ) + + def save(self, title: Optional[str] = None, temporary: bool = False) -> None: + """Saves all changes to the configuration files. + + :param str title: The title of the save. If a title is given, the + configuration will be saved as a new checkpoint and put in a + timestamped directory. + + :param bool temporary: Indicates whether the changes made will + be quickly reversed in the future (ie. challenges) + + :raises .errors.PluginError: If there was an error in + an attempt to save the configuration, or an error creating a + checkpoint + + """ + # save_files = set(self.parser.parsed.keys()) + # self.add_to_checkpoint(save_files, self.save_notes, temporary) + # self.save_notes = "" + + # # Change 'ext' to something else to not override existing conf files + # self.parser.filedump(ext='') + # if title and not temporary: + # self.finalize_checkpoint(title) + + def recovery_routine(self) -> None: + """Revert all previously modified files. + + Reverts all modified files that have not been saved as a checkpoint + + :raises .errors.PluginError: If unable to recover the configuration + + """ + # super().recovery_routine() + # self.new_vhost = None + # self.parser.load() + + def revert_challenge_config(self) -> None: + """Used to cleanup challenge configurations. + + :raises .errors.PluginError: If unable to revert the challenge config. + + """ + # self.revert_temporary_config() + # self.new_vhost = None + # self.parser.load() + + def rollback_checkpoints(self, rollback: int = 1) -> None: + """Rollback saved checkpoints. + + :param int rollback: Number of checkpoints to revert + + :raises .errors.PluginError: If there is a problem with the input or + the function is unable to correctly revert the configuration + + """ + # super().rollback_checkpoints(rollback) + # self.new_vhost = None + # self.parser.load() + + def get_chall_pref(self, unused_domain: str) -> List[Type[challenges.Challenge]]: + """Return list of challenge preferences.""" + return [challenges.HTTP01] + + # Entry point in main.py for performing challenges + def perform(self, achalls: List[achallenges.AnnotatedChallenge] + ) -> List[challenges.ChallengeResponse]: + """Perform the configuration related challenge. + + This function currently assumes all challenges will be fulfilled. + If this turns out not to be the case in the future. Cleanup and + outstanding challenges will have to be designed better. + + """ + self._chall_out += len(achalls) + responses: List[Optional[challenges.ChallengeResponse]] = [None] * len(achalls) + http_doer = iis_http_01.IISHttp01(self) + + for i, achall in enumerate(achalls): + # Currently also have chall_doer hold associated index of the + # challenge. This helps to put all of the responses back together + # when they are all complete. + if not isinstance(achall, achallenges.KeyAuthorizationAnnotatedChallenge): + raise errors.Error("Challenge should be an instance " + "of KeyAuthorizationAnnotatedChallenge") + http_doer.add_chall(achall, i) + + http_response = http_doer.perform() + # Must restart in order to activate the challenges. + # Handled here because we may be able to load up other challenge types + # self.restart() + + # Go through all of the challenges and assign them to the proper place + # in the responses return value. All responses must be in the same order + # as the original challenges. + for i, resp in enumerate(http_response): + responses[http_doer.indices[i]] = resp + + return [response for response in responses if response] + + # called after challenges are performed + def cleanup(self, achalls: List[achallenges.AnnotatedChallenge]) -> None: + """Revert all challenges.""" + self._chall_out -= len(achalls) + + # If all of the challenges have been finished, clean up everything + if self._chall_out <= 0: + self.revert_challenge_config() + # self.restart() + + def enhance(self, domain, enhancement, options=None): + """Perform a configuration enhancement. + + :param str domain: domain for which to provide enhancement + :param str enhancement: An enhancement as defined in + :const:`~certbot.plugins.enhancements.ENHANCEMENTS` + :param options: Flexible options parameter for enhancement. + Check documentation of + :const:`~certbot.plugins.enhancements.ENHANCEMENTS` + for expected options for each enhancement. + + :raises .PluginError: If Enhancement is not supported, or if + an error occurs during the enhancement. + + """ + + def supported_enhancements(self): # type: ignore + """Returns a `collections.Iterable` of supported enhancements. + + :returns: supported enhancements which should be a subset of + :const:`~certbot.plugins.enhancements.ENHANCEMENTS` + :rtype: :class:`collections.Iterable` of :class:`str` + + """ + return [] + + def get_all_names(self): # type: ignore + """Returns all names that may be authenticated. + + :rtype: `collections.Iterable` of `str` + + """ + logger.debug("********inside get all names************") + +def _determine_default_server_root() -> str: + default_server_root = constants.CLI_DEFAULTS["server_root"] + return default_server_root diff --git a/certbot-iis/certbot_iis/_internal/constants.py b/certbot-iis/certbot_iis/_internal/constants.py new file mode 100644 index 00000000000..7de274e74a8 --- /dev/null +++ b/certbot-iis/certbot_iis/_internal/constants.py @@ -0,0 +1,34 @@ +"""iis plugin constants.""" +import platform +from typing import Any +from typing import Dict + +WINDOWS_SERVER_ROOT = "C:\inetpub" + +server_root_tmp = WINDOWS_SERVER_ROOT + +CLI_DEFAULTS: Dict[str, Any] = { + "server_root": server_root_tmp, + "ctl": "iis", + "sleep_seconds": 1 +} +"""CLI defaults.""" + +def os_constant(key: str) -> Any: + # XXX TODO: In the future, this could return different constants + # based on what OS we are running under. To see an + # approach to how to handle different OSes, see the + # apache version of this file. Currently, we do not + # actually have any OS-specific constants on IIs. + """ + Get a constant value for operating system + + :param str key: name of cli constant + :return: value of constant for active os + """ + return CLI_DEFAULTS[key] + + +HSTS_ARGS = ['\"max-age=31536000\"', ' ', 'always'] + +HEADER_ARGS = {'Strict-Transport-Security': HSTS_ARGS} diff --git a/certbot-iis/certbot_iis/_internal/iis_http_01.py b/certbot-iis/certbot_iis/_internal/iis_http_01.py new file mode 100644 index 00000000000..97c24a335fd --- /dev/null +++ b/certbot-iis/certbot_iis/_internal/iis_http_01.py @@ -0,0 +1,48 @@ +"""A class that performs HTTP-01 challenges for IIS""" + +import logging +from typing import List +from typing import TYPE_CHECKING + +from acme.challenges import KeyAuthorizationChallengeResponse +from certbot import util +from certbot.compat import os +from certbot.plugins import common + +if TYPE_CHECKING: + from certbot_iis._internal.configurator import IISConfigurator + +logger = logging.getLogger(__name__) + + +class IISHttp01(common.ChallengePerformer): + """HTTP-01 authenticator for IIS""" + + def __init__(self, configurator) -> None: + super().__init__(configurator) + # self.configurator: "IISConfigurator" + self.challenge_conf = util.escape_char_conv(os.path.join( + configurator.config.config_dir, "le_http_01_cert_challenge.conf")) + + def perform(self) -> List[KeyAuthorizationChallengeResponse]: + """Perform a challenge on IIS . + + :returns: list of :class:`acme.challenges.KeyAuthorizationChallengeResponse` + :rtype: list + + """ + if not self.achalls: + return [] + + responses = [x.response(x.account_key) for x in self.achalls] + + # Set up the configuration + self._mod_config() + + # Save reversible changes + self.configurator.save("HTTP Challenge", True) + + return responses + + def _mod_config(self) -> None: + logger.debug("*****************challanges performed****************") diff --git a/certbot-iis/certbot_iis/py.typed b/certbot-iis/certbot_iis/py.typed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/certbot-iis/setup.py b/certbot-iis/setup.py new file mode 100644 index 00000000000..6d2c24b2c32 --- /dev/null +++ b/certbot-iis/setup.py @@ -0,0 +1,60 @@ +from setuptools import find_packages +from setuptools import setup + +version = '2.6.0.dev0' + +install_requires = [ + # We specify the minimum acme and certbot version as the current plugin + # version for simplicity. See + # https://github.com/certbot/certbot/issues/8761 for more info. + f'acme>={version}', + f'certbot>={version}', + # pyOpenSSL 23.1.0 is a bad release: https://github.com/pyca/pyopenssl/issues/1199 + 'PyOpenSSL>=17.5.0,!=23.1.0', + 'pyparsing>=2.2.1', + 'setuptools>=41.6.0', +] + +test_extras = [ + 'pytest', +] + +setup( + name='certbot-iis', + version=version, + description="IIS plugin for Certbot", + url='https://github.com/letsencrypt/letsencrypt', + author="Certbot Project", + author_email='certbot-dev@eff.org', + license='Apache License 2.0', + python_requires='>=3.7', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Plugins', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Security', + 'Topic :: System :: Installation/Setup', + 'Topic :: System :: Networking', + 'Topic :: System :: Systems Administration', + 'Topic :: Utilities', + ], + + packages=find_packages(), + include_package_data=True, + install_requires=install_requires, + entry_points={ + 'certbot.plugins': [ + 'iis = certbot_iis._internal.configurator:IISConfigurator', + ], + }, +) diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index ce312b5119c..a4647cce3ac 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -466,7 +466,10 @@ def prepare_and_parse_args(plugins: plugins_disco.PluginsRegistry, args: List[st [None,"automation", "certonly", "run","renew"], "--retry-interval",type=int, dest="retry_interval", default=flag_default("retry_interval"), help=config_help("retry_interval")) - + helpful.add( + None, "--iis-cert-name", dest="iis_cert_name", + help="Certificate name for PFX file." + ) # Deprecated arguments helpful.add_deprecated_argument("--os-packages-only", 0) diff --git a/windows-installer/windows_installer/construct.py b/windows-installer/windows_installer/construct.py index ecace123bcd..08942032d0c 100644 --- a/windows-installer/windows_installer/construct.py +++ b/windows-installer/windows_installer/construct.py @@ -52,7 +52,7 @@ def _compile_wheels(repo_path, build_path, venv_python): wheels_path = os.path.join(build_path, 'wheels') os.makedirs(wheels_path) - certbot_packages = ['acme', 'certbot','certbot-nginx','certbot-apache-win','certbot-tomcat'] + certbot_packages = ['acme', 'certbot','certbot-nginx','certbot-apache-win','certbot-tomcat','certbot-iis'] #certbot_packages = ['acme', 'certbot','certbot-nginx','certbot-apache','certbot-apache-win','certbot-tomcat'] # Uncomment following line to include all DNS plugins in the installer # certbot_packages.extend([name for name in os.listdir(repo_path) if name.startswith('certbot-dns-')])