mirror of
https://github.com/certbot/certbot.git
synced 2026-01-26 07:41:33 +03:00
Merge pull request #498 from kuba/simplehttp
SimpleHTTPS -> SimpleHTTP[S]
This commit is contained in:
@@ -42,16 +42,17 @@ class ChallengeResponse(jose.TypedJSONObjectWithFields):
|
||||
|
||||
|
||||
@Challenge.register
|
||||
class SimpleHTTPS(DVChallenge):
|
||||
"""ACME "simpleHttps" challenge."""
|
||||
typ = "simpleHttps"
|
||||
class SimpleHTTP(DVChallenge):
|
||||
"""ACME "simpleHttp" challenge."""
|
||||
typ = "simpleHttp"
|
||||
token = jose.Field("token")
|
||||
tls = jose.Field("tls", default=True, omitempty=True)
|
||||
|
||||
|
||||
@ChallengeResponse.register
|
||||
class SimpleHTTPSResponse(ChallengeResponse):
|
||||
"""ACME "simpleHttps" challenge response."""
|
||||
typ = "simpleHttps"
|
||||
class SimpleHTTPResponse(ChallengeResponse):
|
||||
"""ACME "simpleHttp" challenge response."""
|
||||
typ = "simpleHttp"
|
||||
path = jose.Field("path")
|
||||
|
||||
URI_TEMPLATE = "https://{domain}/.well-known/acme-challenge/{path}"
|
||||
@@ -61,7 +62,7 @@ class SimpleHTTPSResponse(ChallengeResponse):
|
||||
"""Create an URI to the provisioned resource.
|
||||
|
||||
Forms an URI to the HTTPS server provisioned resource (containing
|
||||
:attr:`~SimpleHTTPS.token`) by populating the :attr:`URI_TEMPLATE`.
|
||||
:attr:`~SimpleHTTP.token`) by populating the :attr:`URI_TEMPLATE`.
|
||||
|
||||
:param str domain: Domain name being verified.
|
||||
|
||||
|
||||
@@ -18,36 +18,45 @@ KEY = jose.HashableRSAKey(Crypto.PublicKey.RSA.importKey(
|
||||
'acme.jose', os.path.join('testdata', 'rsa512_key.pem'))))
|
||||
|
||||
|
||||
class SimpleHTTPSTest(unittest.TestCase):
|
||||
class SimpleHTTPTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
from acme.challenges import SimpleHTTPS
|
||||
self.msg = SimpleHTTPS(
|
||||
from acme.challenges import SimpleHTTP
|
||||
self.msg = SimpleHTTP(
|
||||
token='evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA')
|
||||
self.jmsg = {
|
||||
'type': 'simpleHttps',
|
||||
'type': 'simpleHttp',
|
||||
'token': 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA',
|
||||
'tls': True,
|
||||
}
|
||||
|
||||
def test_no_tls(self):
|
||||
from acme.challenges import SimpleHTTP
|
||||
self.assertEqual(SimpleHTTP(token='tok', tls=False).to_json(), {
|
||||
'tls': False,
|
||||
'token': 'tok',
|
||||
'type': 'simpleHttp',
|
||||
})
|
||||
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from acme.challenges import SimpleHTTPS
|
||||
self.assertEqual(self.msg, SimpleHTTPS.from_json(self.jmsg))
|
||||
from acme.challenges import SimpleHTTP
|
||||
self.assertEqual(self.msg, SimpleHTTP.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from acme.challenges import SimpleHTTPS
|
||||
hash(SimpleHTTPS.from_json(self.jmsg))
|
||||
from acme.challenges import SimpleHTTP
|
||||
hash(SimpleHTTP.from_json(self.jmsg))
|
||||
|
||||
|
||||
class SimpleHTTPSResponseTest(unittest.TestCase):
|
||||
class SimpleHTTPResponseTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
from acme.challenges import SimpleHTTPSResponse
|
||||
self.msg = SimpleHTTPSResponse(path='6tbIMBC5Anhl5bOlWT5ZFA')
|
||||
from acme.challenges import SimpleHTTPResponse
|
||||
self.msg = SimpleHTTPResponse(path='6tbIMBC5Anhl5bOlWT5ZFA')
|
||||
self.jmsg = {
|
||||
'type': 'simpleHttps',
|
||||
'type': 'simpleHttp',
|
||||
'path': '6tbIMBC5Anhl5bOlWT5ZFA',
|
||||
}
|
||||
|
||||
@@ -59,13 +68,13 @@ class SimpleHTTPSResponseTest(unittest.TestCase):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from acme.challenges import SimpleHTTPSResponse
|
||||
from acme.challenges import SimpleHTTPResponse
|
||||
self.assertEqual(
|
||||
self.msg, SimpleHTTPSResponse.from_json(self.jmsg))
|
||||
self.msg, SimpleHTTPResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from acme.challenges import SimpleHTTPSResponse
|
||||
hash(SimpleHTTPSResponse.from_json(self.jmsg))
|
||||
from acme.challenges import SimpleHTTPResponse
|
||||
hash(SimpleHTTPResponse.from_json(self.jmsg))
|
||||
|
||||
|
||||
class DVSNITest(unittest.TestCase):
|
||||
|
||||
@@ -62,7 +62,7 @@ class Field(object):
|
||||
definition of being empty, e.g. for some more exotic data types.
|
||||
|
||||
"""
|
||||
return not value
|
||||
return not isinstance(value, bool) and not value
|
||||
|
||||
def omit(self, value):
|
||||
"""Omit the value in output?"""
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Tests for acme.jose.json_util."""
|
||||
import itertools
|
||||
import os
|
||||
import pkg_resources
|
||||
import unittest
|
||||
@@ -20,6 +21,13 @@ CSR = M2Crypto.X509.load_request(pkg_resources.resource_filename(
|
||||
class FieldTest(unittest.TestCase):
|
||||
"""Tests for acme.jose.json_util.Field."""
|
||||
|
||||
def test_no_omit_boolean(self):
|
||||
from acme.jose.json_util import Field
|
||||
for default, omitempty, value in itertools.product(
|
||||
[True, False], [True, False], [True, False]):
|
||||
self.assertFalse(
|
||||
Field("foo", default=default, omitempty=omitempty).omit(value))
|
||||
|
||||
def test_descriptors(self):
|
||||
mock_value = mock.MagicMock()
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ class AuthorizationTest(unittest.TestCase):
|
||||
self.challbs = (
|
||||
ChallengeBody(
|
||||
uri='http://challb1', status=STATUS_VALID,
|
||||
chall=challenges.SimpleHTTPS(token='IlirfxKKXAsHtmzK29Pj8A')),
|
||||
chall=challenges.SimpleHTTP(token='IlirfxKKXAsHtmzK29Pj8A')),
|
||||
ChallengeBody(uri='http://challb2', status=STATUS_VALID,
|
||||
chall=challenges.DNS(token='DGyRejmCefe7v4NfDGDKfA')),
|
||||
ChallengeBody(uri='http://challb3', status=STATUS_VALID,
|
||||
|
||||
@@ -63,7 +63,7 @@ class ChallengeTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
challs = (
|
||||
challenges.SimpleHTTPS(token='IlirfxKKXAsHtmzK29Pj8A'),
|
||||
challenges.SimpleHTTP(token='IlirfxKKXAsHtmzK29Pj8A'),
|
||||
challenges.DNS(token='DGyRejmCefe7v4NfDGDKfA'),
|
||||
challenges.RecoveryToken(),
|
||||
)
|
||||
@@ -94,7 +94,7 @@ class ChallengeTest(unittest.TestCase):
|
||||
def test_resolved_combinations(self):
|
||||
self.assertEqual(self.msg.resolved_combinations, (
|
||||
(
|
||||
challenges.SimpleHTTPS(token='IlirfxKKXAsHtmzK29Pj8A'),
|
||||
challenges.SimpleHTTP(token='IlirfxKKXAsHtmzK29Pj8A'),
|
||||
challenges.RecoveryToken()
|
||||
),
|
||||
(
|
||||
@@ -183,7 +183,7 @@ class AuthorizationRequestTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.responses = (
|
||||
challenges.SimpleHTTPSResponse(path='Hf5GrX4Q7EBax9hc2jJnfw'),
|
||||
challenges.SimpleHTTPResponse(path='Hf5GrX4Q7EBax9hc2jJnfw'),
|
||||
None, # null
|
||||
challenges.RecoveryTokenResponse(token='23029d88d9e123e'),
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"required": ["type", "token"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum" : [ "simpleHttps" ]
|
||||
"enum" : [ "simpleHttp" ]
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"required": ["type", "path"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum" : [ "simpleHttps" ]
|
||||
"enum" : [ "simpleHttp" ]
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
|
||||
@@ -62,10 +62,10 @@ class DVSNI(AnnotatedChallenge):
|
||||
return cert_pem, response
|
||||
|
||||
|
||||
class SimpleHTTPS(AnnotatedChallenge):
|
||||
"""Client annotated "simpleHttps" ACME challenge."""
|
||||
class SimpleHTTP(AnnotatedChallenge):
|
||||
"""Client annotated "simpleHttp" ACME challenge."""
|
||||
__slots__ = ('challb', 'domain', 'key')
|
||||
acme_type = challenges.SimpleHTTPS
|
||||
acme_type = challenges.SimpleHTTP
|
||||
|
||||
|
||||
class DNS(AnnotatedChallenge):
|
||||
|
||||
@@ -336,9 +336,9 @@ def challb_to_achall(challb, key, domain):
|
||||
logging.info(" DVSNI challenge for %s.", domain)
|
||||
return achallenges.DVSNI(
|
||||
challb=challb, domain=domain, key=key)
|
||||
elif isinstance(chall, challenges.SimpleHTTPS):
|
||||
logging.info(" SimpleHTTPS challenge for %s.", domain)
|
||||
return achallenges.SimpleHTTPS(
|
||||
elif isinstance(chall, challenges.SimpleHTTP):
|
||||
logging.info(" SimpleHTTP challenge for %s.", domain)
|
||||
return achallenges.SimpleHTTP(
|
||||
challb=challb, domain=domain, key=key)
|
||||
elif isinstance(chall, challenges.DNS):
|
||||
logging.info(" DNS challenge for %s.", domain)
|
||||
|
||||
@@ -252,6 +252,9 @@ def create_parser(plugins):
|
||||
add("-t", "--text", dest="text_mode", action="store_true",
|
||||
help="Use the text output instead of the curses UI.")
|
||||
|
||||
add("--no-simple-http-tls", action="store_true",
|
||||
help=config_help("no_simple_http_tls"))
|
||||
|
||||
testing_group = parser.add_argument_group(
|
||||
"testing", description="The following flags are meant for "
|
||||
"testing purposes only! Do NOT change them, unless you "
|
||||
|
||||
@@ -41,7 +41,7 @@ RENEWER_DEFAULTS = dict(
|
||||
|
||||
|
||||
EXCLUSIVE_CHALLENGES = frozenset([frozenset([
|
||||
challenges.DVSNI, challenges.SimpleHTTPS])])
|
||||
challenges.DVSNI, challenges.SimpleHTTP])])
|
||||
"""Mutually exclusive challenges."""
|
||||
|
||||
|
||||
|
||||
@@ -188,6 +188,10 @@ class IConfig(zope.interface.Interface):
|
||||
"Port number to perform DVSNI challenge. "
|
||||
"Boulder in testing mode defaults to 5001.")
|
||||
|
||||
# TODO: not implemented
|
||||
no_simple_http_tls = zope.interface.Attribute(
|
||||
"Do not use TLS when solving SimpleHTTP challenges.")
|
||||
|
||||
|
||||
class IInstaller(IPlugin):
|
||||
"""Generic Let's Encrypt Installer Interface.
|
||||
|
||||
@@ -16,7 +16,7 @@ KEY = jose.HashableRSAKey(Crypto.PublicKey.RSA.importKey(
|
||||
"acme.jose", os.path.join("testdata", "rsa512_key.pem"))))
|
||||
|
||||
# Challenges
|
||||
SIMPLE_HTTPS = challenges.SimpleHTTPS(
|
||||
SIMPLE_HTTPS = challenges.SimpleHTTP(
|
||||
token="evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA")
|
||||
DVSNI = challenges.DVSNI(
|
||||
r="O*\xb4-\xad\xec\x95>\xed\xa9\r0\x94\xe8\x97\x9c&6\xbf'\xb3"
|
||||
|
||||
@@ -17,7 +17,7 @@ from letsencrypt.tests import acme_util
|
||||
|
||||
TRANSLATE = {
|
||||
"dvsni": "DVSNI",
|
||||
"simpleHttps": "SimpleHTTPS",
|
||||
"simpleHttp": "SimpleHTTP",
|
||||
"dns": "DNS",
|
||||
"recoveryToken": "RecoveryToken",
|
||||
"recoveryContact": "RecoveryContact",
|
||||
@@ -299,7 +299,7 @@ class GenChallengePathTest(unittest.TestCase):
|
||||
return gen_challenge_path(challbs, preferences, combinations)
|
||||
|
||||
def test_common_case(self):
|
||||
"""Given DVSNI and SimpleHTTPS with appropriate combos."""
|
||||
"""Given DVSNI and SimpleHTTP with appropriate combos."""
|
||||
challbs = (acme_util.DVSNI_P, acme_util.SIMPLE_HTTPS_P)
|
||||
prefs = [challenges.DVSNI]
|
||||
combos = ((0,), (1,))
|
||||
@@ -334,7 +334,7 @@ class GenChallengePathTest(unittest.TestCase):
|
||||
# Attempted to make the order realistic
|
||||
prefs = [challenges.RecoveryToken,
|
||||
challenges.ProofOfPossession,
|
||||
challenges.SimpleHTTPS,
|
||||
challenges.SimpleHTTP,
|
||||
challenges.DVSNI,
|
||||
challenges.RecoveryContact]
|
||||
combos = acme_util.gen_combos(challbs)
|
||||
@@ -403,8 +403,8 @@ class IsPreferredTest(unittest.TestCase):
|
||||
def _call(cls, chall, satisfied):
|
||||
from letsencrypt.auth_handler import is_preferred
|
||||
return is_preferred(chall, satisfied, exclusive_groups=frozenset([
|
||||
frozenset([challenges.DVSNI, challenges.SimpleHTTPS]),
|
||||
frozenset([challenges.DNS, challenges.SimpleHTTPS]),
|
||||
frozenset([challenges.DVSNI, challenges.SimpleHTTP]),
|
||||
frozenset([challenges.DNS, challenges.SimpleHTTP]),
|
||||
]))
|
||||
|
||||
def test_empty_satisfied(self):
|
||||
|
||||
@@ -18,7 +18,7 @@ class ApacheDvsni(object):
|
||||
larger array. ApacheDvsni is capable of solving many challenges
|
||||
at once which causes an indexing issue within ApacheConfigurator
|
||||
who must return all responses in order. Imagine ApacheConfigurator
|
||||
maintaining state about where all of the SimpleHTTPS Challenges,
|
||||
maintaining state about where all of the SimpleHTTP Challenges,
|
||||
Dvsni Challenges belong in the response array. This is an optional
|
||||
utility.
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class NginxDvsni(ApacheDvsni):
|
||||
larger array. NginxDvsni is capable of solving many challenges
|
||||
at once which causes an indexing issue within NginxConfigurator
|
||||
who must return all responses in order. Imagine NginxConfigurator
|
||||
maintaining state about where all of the SimpleHTTPS Challenges,
|
||||
maintaining state about where all of the SimpleHTTP Challenges,
|
||||
Dvsni Challenges belong in the response array. This is an optional
|
||||
utility.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user