Add new common utils tests
Change-Id: I38ac7accf5fd90e402072dc6074c3ca2f2d46509
This commit is contained in:
parent
4610369f28
commit
b9c863e351
|
@ -50,30 +50,6 @@ LOG = logging.getLogger(__name__)
|
|||
GLARE_TEST_SOCKET_FD_STR = 'GLARE_TEST_SOCKET_FD'
|
||||
|
||||
|
||||
def chunkreadable(iter, chunk_size=65536):
|
||||
"""Wrap a readable iterator with a reader yielding chunks of
|
||||
a preferred size, otherwise leave iterator unchanged.
|
||||
|
||||
:param iter: an iter which may also be readable
|
||||
:param chunk_size: maximum size of chunk
|
||||
"""
|
||||
return chunkiter(iter, chunk_size) if hasattr(iter, 'read') else iter
|
||||
|
||||
|
||||
def chunkiter(fp, chunk_size=65536):
|
||||
"""Return an iterator to a file-like obj which yields fixed size chunks.
|
||||
|
||||
:param fp: a file-like object
|
||||
:param chunk_size: maximum size of chunk
|
||||
"""
|
||||
while True:
|
||||
chunk = fp.read(chunk_size)
|
||||
if chunk:
|
||||
yield chunk
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def cooperative_iter(iter):
|
||||
"""Return an iterator which schedules after each
|
||||
iteration. This can prevent eventlet thread starvation.
|
||||
|
@ -174,7 +150,7 @@ class CooperativeReader(object):
|
|||
# check should never fire. Regardless it still worths to
|
||||
# make the check, as the code may be reused somewhere else.
|
||||
if len(result) >= MAX_COOP_READER_BUFFER_SIZE:
|
||||
raise exception.LimitExceeded()
|
||||
raise exception.RequestEntityTooLarge()
|
||||
self.position += len(chunk)
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -13,10 +13,16 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from glare.common import exception as exc
|
||||
from glare.tests.unit import base
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import glare.common.utils as utils
|
||||
import mock
|
||||
from OpenSSL import crypto
|
||||
import six
|
||||
|
||||
from glare.common import exception as exc
|
||||
from glare.common import utils
|
||||
from glare.tests.unit import base
|
||||
|
||||
|
||||
class TestUtils(base.BaseTestCase):
|
||||
|
@ -39,14 +45,252 @@ class TestUtils(base.BaseTestCase):
|
|||
self.assertRaises(exc.InvalidParameterValue,
|
||||
utils.validate_quotes, '"The quote is not closed')
|
||||
|
||||
def test_no_4bytes_params(self):
|
||||
@utils.no_4byte_params
|
||||
def test_func(*args, **kwargs):
|
||||
return args, kwargs
|
||||
|
||||
bad_char = u'\U0001f62a'
|
||||
|
||||
# params without 4bytes unicode are okay
|
||||
args, kwargs = test_func('val1', param='val2')
|
||||
self.assertEqual(('val1',), args)
|
||||
self.assertEqual({'param': 'val2'}, kwargs)
|
||||
|
||||
# test various combinations with bad param
|
||||
self.assertRaises(exc.BadRequest, test_func,
|
||||
bad_char)
|
||||
self.assertRaises(exc.BadRequest, test_func,
|
||||
**{bad_char: 'val1'})
|
||||
self.assertRaises(exc.BadRequest, test_func,
|
||||
**{'param': bad_char})
|
||||
|
||||
class TestUtilsDictDiff(base.BaseTestCase):
|
||||
"""tests for utils.DictDiffer class"""
|
||||
def test_str_repr(self):
|
||||
past_dict = {"a": 1, "b": 2, "d": 4}
|
||||
current_dic = {"b": 2, "d": "different value!", "e": "new!"}
|
||||
dict_diff = utils.DictDiffer(current_dic, past_dict)
|
||||
|
||||
self.assertEqual({'a'}, dict_diff.removed())
|
||||
self.assertEqual({'b'}, dict_diff.unchanged())
|
||||
self.assertEqual({'d'}, dict_diff.changed())
|
||||
self.assertEqual({'e'}, dict_diff.added())
|
||||
|
||||
expected_dict_str = "\nResult output:\n\tAdded keys: " \
|
||||
"e\n\tRemoved keys:" \
|
||||
" a\n\tChanged keys: d\n\tUnchanged keys: b\n"
|
||||
self.assertEqual(str(dict_diff), expected_dict_str)
|
||||
|
||||
|
||||
class TestReaders(base.BaseTestCase):
|
||||
"""Test various readers in glare.common.utils"""
|
||||
|
||||
def test_cooperative_reader_iterator(self):
|
||||
"""Ensure cooperative reader class accesses all bytes of file"""
|
||||
BYTES = 1024
|
||||
bytes_read = 0
|
||||
with tempfile.TemporaryFile('w+') as tmp_fd:
|
||||
tmp_fd.write('*' * BYTES)
|
||||
tmp_fd.seek(0)
|
||||
for chunk in utils.CooperativeReader(tmp_fd):
|
||||
bytes_read += len(chunk)
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
def test_cooperative_reader_explicit_read(self):
|
||||
BYTES = 1024
|
||||
bytes_read = 0
|
||||
with tempfile.TemporaryFile('w+') as tmp_fd:
|
||||
tmp_fd.write('*' * BYTES)
|
||||
tmp_fd.seek(0)
|
||||
reader = utils.CooperativeReader(tmp_fd)
|
||||
byte = reader.read(1)
|
||||
while len(byte) != 0:
|
||||
bytes_read += 1
|
||||
byte = reader.read(1)
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
def test_cooperative_reader_no_read_method(self):
|
||||
BYTES = 1024
|
||||
stream = [b'*'] * BYTES
|
||||
reader = utils.CooperativeReader(stream)
|
||||
bytes_read = 0
|
||||
byte = reader.read()
|
||||
while len(byte) != 0:
|
||||
bytes_read += 1
|
||||
byte = reader.read()
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
# some data may be left in the buffer
|
||||
reader = utils.CooperativeReader(stream)
|
||||
reader.buffer = 'some data'
|
||||
buffer_string = reader.read()
|
||||
self.assertEqual('some data', buffer_string)
|
||||
|
||||
def test_cooperative_reader_no_read_method_buffer_size(self):
|
||||
# Decrease buffer size to 1000 bytes to test its overflow
|
||||
with mock.patch('glare.common.utils.MAX_COOP_READER_BUFFER_SIZE',
|
||||
1000):
|
||||
BYTES = 1024
|
||||
stream = [b'*'] * BYTES
|
||||
reader = utils.CooperativeReader(stream)
|
||||
# Reading 1001 bytes to the buffer leads to 413 error
|
||||
self.assertRaises(exc.RequestEntityTooLarge, reader.read, 1001)
|
||||
|
||||
def test_cooperative_reader_of_iterator(self):
|
||||
"""Ensure cooperative reader supports iterator backends too"""
|
||||
data = b'abcdefgh'
|
||||
data_list = [data[i:i + 1] * 3 for i in range(len(data))]
|
||||
reader = utils.CooperativeReader(data_list)
|
||||
chunks = []
|
||||
while True:
|
||||
chunks.append(reader.read(3))
|
||||
if chunks[-1] == b'':
|
||||
break
|
||||
meat = b''.join(chunks)
|
||||
self.assertEqual(b'aaabbbcccdddeeefffggghhh', meat)
|
||||
|
||||
def test_cooperative_reader_of_iterator_stop_iteration_err(self):
|
||||
"""Ensure cooperative reader supports iterator backends too"""
|
||||
reader = utils.CooperativeReader([l * 3 for l in ''])
|
||||
chunks = []
|
||||
while True:
|
||||
chunks.append(reader.read(3))
|
||||
if chunks[-1] == b'':
|
||||
break
|
||||
meat = b''.join(chunks)
|
||||
self.assertEqual(b'', meat)
|
||||
|
||||
def _create_generator(self, chunk_size, max_iterations):
|
||||
chars = b'abc'
|
||||
iteration = 0
|
||||
while True:
|
||||
index = iteration % len(chars)
|
||||
chunk = chars[index:index + 1] * chunk_size
|
||||
yield chunk
|
||||
iteration += 1
|
||||
if iteration >= max_iterations:
|
||||
raise StopIteration()
|
||||
|
||||
def _test_reader_chunked(self, chunk_size, read_size, max_iterations=5):
|
||||
generator = self._create_generator(chunk_size, max_iterations)
|
||||
reader = utils.CooperativeReader(generator)
|
||||
result = bytearray()
|
||||
while True:
|
||||
data = reader.read(read_size)
|
||||
if len(data) == 0:
|
||||
break
|
||||
self.assertLessEqual(len(data), read_size)
|
||||
result += data
|
||||
expected = (b'a' * chunk_size +
|
||||
b'b' * chunk_size +
|
||||
b'c' * chunk_size +
|
||||
b'a' * chunk_size +
|
||||
b'b' * chunk_size)
|
||||
self.assertEqual(expected, bytes(result))
|
||||
|
||||
def test_cooperative_reader_preserves_size_chunk_less_then_read(self):
|
||||
self._test_reader_chunked(43, 101)
|
||||
|
||||
def test_cooperative_reader_preserves_size_chunk_equals_read(self):
|
||||
self._test_reader_chunked(1024, 1024)
|
||||
|
||||
def test_cooperative_reader_preserves_size_chunk_more_then_read(self):
|
||||
chunk_size = 16 * 1024 * 1024 # 16 Mb, as in remote http source
|
||||
read_size = 8 * 1024 # 8k, as in httplib
|
||||
self._test_reader_chunked(chunk_size, read_size)
|
||||
|
||||
def test_limiting_reader(self):
|
||||
"""Ensure limiting reader class accesses all bytes of file"""
|
||||
BYTES = 1024
|
||||
bytes_read = 0
|
||||
data = six.BytesIO(b"*" * BYTES)
|
||||
for chunk in utils.LimitingReader(data, BYTES):
|
||||
bytes_read += len(chunk)
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
bytes_read = 0
|
||||
data = six.BytesIO(b"*" * BYTES)
|
||||
reader = utils.LimitingReader(data, BYTES)
|
||||
byte = reader.read(1)
|
||||
while len(byte) != 0:
|
||||
bytes_read += 1
|
||||
byte = reader.read(1)
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
def test_limiting_reader_fails(self):
|
||||
"""Ensure limiting reader class throws exceptions if limit exceeded"""
|
||||
BYTES = 1024
|
||||
|
||||
def _consume_all_iter():
|
||||
bytes_read = 0
|
||||
data = six.BytesIO(b"*" * BYTES)
|
||||
for chunk in utils.LimitingReader(data, BYTES - 1):
|
||||
bytes_read += len(chunk)
|
||||
|
||||
self.assertRaises(exc.RequestEntityTooLarge, _consume_all_iter)
|
||||
|
||||
def _consume_all_read():
|
||||
bytes_read = 0
|
||||
data = six.BytesIO(b"*" * BYTES)
|
||||
reader = utils.LimitingReader(data, BYTES - 1)
|
||||
byte = reader.read(1)
|
||||
while len(byte) != 0:
|
||||
bytes_read += 1
|
||||
byte = reader.read(1)
|
||||
|
||||
self.assertRaises(exc.RequestEntityTooLarge, _consume_all_read)
|
||||
|
||||
def test_blob_iterator(self):
|
||||
BYTES = 1024
|
||||
bytes_read = 0
|
||||
stream = [b'*'] * BYTES
|
||||
for chunk in utils.BlobIterator(stream, 64):
|
||||
bytes_read += len(chunk)
|
||||
|
||||
self.assertEqual(BYTES, bytes_read)
|
||||
|
||||
|
||||
class TestKeyCert(base.BaseTestCase):
|
||||
|
||||
def test_validate_key_cert_key(self):
|
||||
var_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'../', 'var'))
|
||||
keyfile = os.path.join(var_dir, 'privatekey.key')
|
||||
certfile = os.path.join(var_dir, 'certificate.crt')
|
||||
utils.validate_key_cert(keyfile, certfile)
|
||||
|
||||
def test_validate_key_cert_no_private_key(self):
|
||||
with tempfile.NamedTemporaryFile('w+') as tmpf:
|
||||
self.assertRaises(RuntimeError,
|
||||
utils.validate_key_cert,
|
||||
"/not/a/file", tmpf.name)
|
||||
|
||||
def test_validate_key_cert_cert_cant_read(self):
|
||||
with tempfile.NamedTemporaryFile('w+') as keyf:
|
||||
with tempfile.NamedTemporaryFile('w+') as certf:
|
||||
os.chmod(certf.name, 0)
|
||||
self.assertRaises(RuntimeError,
|
||||
utils.validate_key_cert,
|
||||
keyf.name, certf.name)
|
||||
|
||||
def test_validate_key_cert_key_cant_read(self):
|
||||
with tempfile.NamedTemporaryFile('w+') as keyf:
|
||||
with tempfile.NamedTemporaryFile('w+') as certf:
|
||||
os.chmod(keyf.name, 0)
|
||||
self.assertRaises(RuntimeError,
|
||||
utils.validate_key_cert,
|
||||
keyf.name, certf.name)
|
||||
|
||||
def test_validate_key_cert_key_crypto_error(self):
|
||||
var_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'../', 'var'))
|
||||
keyfile = os.path.join(var_dir, 'privatekey.key')
|
||||
certfile = os.path.join(var_dir, 'certificate.crt')
|
||||
with mock.patch('OpenSSL.crypto.verify', side_effect=crypto.Error):
|
||||
self.assertRaises(RuntimeError,
|
||||
utils.validate_key_cert,
|
||||
keyfile, certfile)
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
# > openssl x509 -in glare/tests/var/certificate.crt -noout -text
|
||||
# Certificate:
|
||||
# Data:
|
||||
# Version: 1 (0x0)
|
||||
# Serial Number: 1 (0x1)
|
||||
# Signature Algorithm: sha1WithRSAEncryption
|
||||
# Issuer: C=AU, ST=Some-State, O=OpenStack, OU=Glare, CN=Glare CA
|
||||
# Validity
|
||||
# Not Before: Feb 2 20:22:13 2015 GMT
|
||||
# Not After : Jan 31 20:22:13 2024 GMT
|
||||
# Subject: C=AU, ST=Some-State, O=OpenStack, OU=Glare, CN=127.0.0.1
|
||||
# Subject Public Key Info:
|
||||
# Public Key Algorithm: rsaEncryption
|
||||
# RSA Public Key: (4096 bit)
|
||||
# Modulus (4096 bit):
|
||||
# 00:9f:44:13:51:de:e9:5a:f7:ac:33:2a:1a:4c:91:
|
||||
# a1:73:bc:f3:a6:d3:e6:59:ae:e8:e2:34:68:3e:f4:
|
||||
# 40:c1:a1:1a:65:9a:a3:67:e9:2c:b9:79:9c:00:b1:
|
||||
# 7c:c1:e6:9e:de:47:bf:f1:cb:f2:73:d4:c3:62:fe:
|
||||
# 82:90:6f:b4:75:ca:7e:56:8f:99:3d:06:51:3c:40:
|
||||
# f4:ff:74:97:4f:0d:d2:e6:66:76:8d:97:bf:89:ce:
|
||||
# fe:b2:d7:89:71:f2:a0:d9:f5:26:7c:1a:7a:bf:2b:
|
||||
# 8f:72:80:e7:1f:4d:4a:40:a3:b9:9e:33:f6:55:e0:
|
||||
# 40:2b:1e:49:e4:8c:71:9d:11:32:cf:21:41:e1:13:
|
||||
# 28:c6:d6:f6:e0:b3:26:10:6d:5b:63:1d:c3:ee:d0:
|
||||
# c4:66:63:38:89:6b:8f:2a:c2:bd:4f:e4:bc:03:8f:
|
||||
# a2:f2:5c:1d:73:11:9c:7b:93:3d:d6:a3:d1:2d:cd:
|
||||
# 64:23:24:bc:65:3c:71:20:28:60:a0:ea:fe:77:0e:
|
||||
# 1d:95:36:76:ad:e7:2f:1c:27:62:55:e3:9d:11:c1:
|
||||
# fb:43:3e:e5:21:ac:fd:0e:7e:3d:c9:44:d2:bd:6f:
|
||||
# 89:7e:0f:cb:88:54:57:fd:8d:21:c8:34:e1:47:01:
|
||||
# 28:0f:45:a1:7e:60:1a:9c:4c:0c:b8:c1:37:2d:46:
|
||||
# ab:18:9e:ca:49:d3:77:b7:92:3a:d2:7f:ca:d5:02:
|
||||
# f1:75:81:66:39:51:aa:bc:d7:f0:91:23:69:e8:71:
|
||||
# ae:44:76:5e:87:54:eb:72:fc:ac:fd:60:22:e0:6a:
|
||||
# e4:ad:37:b7:f6:e5:24:b4:95:2c:26:0e:75:a0:e9:
|
||||
# ed:57:be:37:42:64:1f:02:49:0c:bd:5d:74:6d:e6:
|
||||
# f2:da:5c:54:82:fa:fc:ff:3a:e4:1a:7a:a9:3c:3d:
|
||||
# ee:b5:df:09:0c:69:c3:51:92:67:80:71:9b:10:8b:
|
||||
# 20:ff:a2:5e:c5:f2:86:a0:06:65:1c:42:f9:91:24:
|
||||
# 54:29:ed:7e:ec:db:4c:7b:54:ee:b1:25:1b:38:53:
|
||||
# ae:01:b6:c5:93:1e:a3:4d:1b:e8:73:47:50:57:e8:
|
||||
# ec:a0:80:53:b1:34:74:37:9a:c1:8c:14:64:2e:16:
|
||||
# dd:a1:2e:d3:45:3e:2c:46:62:20:2a:93:7a:92:4c:
|
||||
# b2:cc:64:47:ad:63:32:0b:68:0c:24:98:20:83:08:
|
||||
# 35:74:a7:68:7a:ef:d6:84:07:d1:5e:d7:c0:6c:3f:
|
||||
# a7:4a:78:62:a8:70:75:37:fb:ce:1f:09:1e:7c:11:
|
||||
# 35:cc:b3:5a:a3:cc:3f:35:c9:ee:24:6f:63:f8:54:
|
||||
# 6f:7c:5b:b4:76:3d:f2:81:6d:ad:64:66:10:d0:c4:
|
||||
# 0b:2c:2f
|
||||
# Exponent: 65537 (0x10001)
|
||||
# Signature Algorithm: sha1WithRSAEncryption
|
||||
# 5f:e8:a8:93:20:6c:0f:12:90:a6:e2:64:21:ed:63:0e:8c:e0:
|
||||
# 0f:d5:04:13:4d:2a:e9:a5:91:b7:e4:51:94:bd:0a:70:4b:94:
|
||||
# c7:1c:94:ed:d7:64:95:07:6b:a1:4a:bc:0b:53:b5:1a:7e:f1:
|
||||
# 9c:12:59:24:5f:36:72:34:ca:33:ee:28:46:fd:21:e6:52:19:
|
||||
# 0c:3d:94:6b:bd:cb:76:a1:45:7f:30:7b:71:f1:84:b6:3c:e0:
|
||||
# ac:af:13:81:9c:0e:6e:3c:9b:89:19:95:de:8e:9c:ef:70:ac:
|
||||
# 07:ae:74:42:47:35:50:88:36:ec:32:1a:55:24:08:f2:44:57:
|
||||
# 67:fe:0a:bb:6b:a7:bd:bc:af:bf:2a:e4:dd:53:84:6b:de:1d:
|
||||
# 2a:28:21:38:06:7a:5b:d8:83:15:65:31:6d:61:67:00:9e:1a:
|
||||
# 61:85:15:a2:4c:9a:eb:6d:59:8e:34:ac:2c:d5:24:4e:00:ff:
|
||||
# 30:4d:a3:d5:80:63:17:52:65:ac:7f:f4:0a:8e:56:a4:97:51:
|
||||
# 39:81:ae:e8:cb:52:09:b3:47:b4:fd:1b:e2:04:f9:f2:76:e3:
|
||||
# 63:ef:90:aa:54:98:96:05:05:a9:91:76:18:ed:5d:9e:6e:88:
|
||||
# 50:9a:f7:2c:ce:5e:54:ba:15:ec:62:ff:5d:be:af:35:03:b1:
|
||||
# 3f:32:3e:0e
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEKjCCAxICAQEwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV
|
||||
BAgMClNvbWUtU3RhdGUxEjAQBgNVBAoMCU9wZW5TdGFjazEPMA0GA1UECwwGR2xh
|
||||
bmNlMRIwEAYDVQQDDAlHbGFuY2UgQ0EwHhcNMTUwMjAyMjAyMjEzWhcNMjQwMTMx
|
||||
MjAyMjEzWjBbMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTESMBAG
|
||||
A1UEChMJT3BlblN0YWNrMQ8wDQYDVQQLEwZHbGFuY2UxEjAQBgNVBAMTCTEyNy4w
|
||||
LjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ9EE1He6Vr3rDMq
|
||||
GkyRoXO886bT5lmu6OI0aD70QMGhGmWao2fpLLl5nACxfMHmnt5Hv/HL8nPUw2L+
|
||||
gpBvtHXKflaPmT0GUTxA9P90l08N0uZmdo2Xv4nO/rLXiXHyoNn1Jnwaer8rj3KA
|
||||
5x9NSkCjuZ4z9lXgQCseSeSMcZ0RMs8hQeETKMbW9uCzJhBtW2Mdw+7QxGZjOIlr
|
||||
jyrCvU/kvAOPovJcHXMRnHuTPdaj0S3NZCMkvGU8cSAoYKDq/ncOHZU2dq3nLxwn
|
||||
YlXjnRHB+0M+5SGs/Q5+PclE0r1viX4Py4hUV/2NIcg04UcBKA9FoX5gGpxMDLjB
|
||||
Ny1GqxieyknTd7eSOtJ/ytUC8XWBZjlRqrzX8JEjaehxrkR2XodU63L8rP1gIuBq
|
||||
5K03t/blJLSVLCYOdaDp7Ve+N0JkHwJJDL1ddG3m8tpcVIL6/P865Bp6qTw97rXf
|
||||
CQxpw1GSZ4BxmxCLIP+iXsXyhqAGZRxC+ZEkVCntfuzbTHtU7rElGzhTrgG2xZMe
|
||||
o00b6HNHUFfo7KCAU7E0dDeawYwUZC4W3aEu00U+LEZiICqTepJMssxkR61jMgto
|
||||
DCSYIIMINXSnaHrv1oQH0V7XwGw/p0p4YqhwdTf7zh8JHnwRNcyzWqPMPzXJ7iRv
|
||||
Y/hUb3xbtHY98oFtrWRmENDECywvAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAF/o
|
||||
qJMgbA8SkKbiZCHtYw6M4A/VBBNNKumlkbfkUZS9CnBLlMcclO3XZJUHa6FKvAtT
|
||||
tRp+8ZwSWSRfNnI0yjPuKEb9IeZSGQw9lGu9y3ahRX8we3HxhLY84KyvE4GcDm48
|
||||
m4kZld6OnO9wrAeudEJHNVCINuwyGlUkCPJEV2f+Crtrp728r78q5N1ThGveHSoo
|
||||
ITgGelvYgxVlMW1hZwCeGmGFFaJMmuttWY40rCzVJE4A/zBNo9WAYxdSZax/9AqO
|
||||
VqSXUTmBrujLUgmzR7T9G+IE+fJ242PvkKpUmJYFBamRdhjtXZ5uiFCa9yzOXlS6
|
||||
Fexi/12+rzUDsT8yPg4=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKAIBAAKCAgEAn0QTUd7pWvesMyoaTJGhc7zzptPmWa7o4jRoPvRAwaEaZZqj
|
||||
Z+ksuXmcALF8weae3ke/8cvyc9TDYv6CkG+0dcp+Vo+ZPQZRPED0/3SXTw3S5mZ2
|
||||
jZe/ic7+steJcfKg2fUmfBp6vyuPcoDnH01KQKO5njP2VeBAKx5J5IxxnREyzyFB
|
||||
4RMoxtb24LMmEG1bYx3D7tDEZmM4iWuPKsK9T+S8A4+i8lwdcxGce5M91qPRLc1k
|
||||
IyS8ZTxxIChgoOr+dw4dlTZ2recvHCdiVeOdEcH7Qz7lIaz9Dn49yUTSvW+Jfg/L
|
||||
iFRX/Y0hyDThRwEoD0WhfmAanEwMuME3LUarGJ7KSdN3t5I60n/K1QLxdYFmOVGq
|
||||
vNfwkSNp6HGuRHZeh1Trcvys/WAi4GrkrTe39uUktJUsJg51oOntV743QmQfAkkM
|
||||
vV10beby2lxUgvr8/zrkGnqpPD3utd8JDGnDUZJngHGbEIsg/6JexfKGoAZlHEL5
|
||||
kSRUKe1+7NtMe1TusSUbOFOuAbbFkx6jTRvoc0dQV+jsoIBTsTR0N5rBjBRkLhbd
|
||||
oS7TRT4sRmIgKpN6kkyyzGRHrWMyC2gMJJgggwg1dKdoeu/WhAfRXtfAbD+nSnhi
|
||||
qHB1N/vOHwkefBE1zLNao8w/NcnuJG9j+FRvfFu0dj3ygW2tZGYQ0MQLLC8CAwEA
|
||||
AQKCAgBL4IvvymqUu0CgE6P57LvlvxS522R4P7uV4W/05jtfxJgl5fmJzO5Q4x4u
|
||||
umB8pJn1vms1EHxPMQNxS1364C0ynSl5pepUx4i2UyAmAG8B680ZlaFPrgdD6Ykw
|
||||
vT0vO2/kx0XxhFAMef1aiQ0TvaftidMqCwmGOlN393Mu3rZWJVZ2lhqj15Pqv4lY
|
||||
3iD5XJBYdVrekTmwqf7KgaLwtVyqDoiAjdMM8lPZeX965FhmxR8oWh0mHR9gf95J
|
||||
etMmdy6Km//+EbeS/HxWRnE0CD/RsQA7NmDFnXvmhsB6/j4EoHn5xB6ssbpGAxIg
|
||||
JwlY4bUrKXpaEgE7i4PYFb1q5asnTDdUZYAGAGXSBbDiUZM2YOe1aaFB/SA3Y3K2
|
||||
47brnx7UXhAXSPJ16EZHejSeFbzZfWgj2J1t3DLk18Fpi/5AxxIy/N5J38kcP7xZ
|
||||
RIcSV1QEasYUrHI9buhuJ87tikDBDFEIIeLZxlyeIdwmKrQ7Vzny5Ls94Wg+2UtI
|
||||
XFLDak5SEugdp3LmmTJaugF+s/OiglBVhcaosoKRXb4K29M7mQv2huEAerFA14Bd
|
||||
dp2KByd8ue+fJrAiSxhAyMDAe/uv0ixnmBBtMH0YYHbfUIgl+kR1Ns/bxrJu7T7F
|
||||
kBQWZV4NRbSRB+RGOG2/Ai5jxu0uLu3gtHMO4XzzElWqzHEDoQKCAQEAzfaSRA/v
|
||||
0831TDL8dmOCO61TQ9GtAa8Ouj+SdyTwk9f9B7NqQWg7qdkbQESpaDLvWYiftoDw
|
||||
mBFHLZe/8RHBaQpEAfbC/+DO6c7O+g1/0Cls33D5VaZOzFnnbHktT3r5xwkZfVBS
|
||||
aPPWl/IZOU8TtNqujQA+mmSnrJ7IuXSsBVq71xgBQT9JBZpUcjZ4eQducmtC43CP
|
||||
GqcSjq559ZKc/sa3PkAtNlKzSUS1abiMcJ86C9PgQ9gOu7y8SSqQ3ivZkVM99rxm
|
||||
wo8KehCcHOPOcIUQKmx4Bs4V3chm8rvygf3aanUHi83xaMeFtIIuOgAJmE9wGQeo
|
||||
k0UGvKBUDIenfwKCAQEAxfVFVxMBfI4mHrgTj/HOq7GMts8iykJK1PuELU6FZhex
|
||||
XOqXRbQ5dCLsyehrKlVPFqUENhXNHaOQrCOZxiVoRje2PfU/1fSqRaPxI7+W1Fsh
|
||||
Fq4PkdJ66NJZJkK5NHwE8SyQf+wpLdL3YhY5LM3tWdX5U9Rr6N8qelE3sLPssAak
|
||||
1km4/428+rkp1BlCffr3FyL0KJmOYfMiAr8m6hRZWbhkvm5YqX1monxUrKdFJ218
|
||||
dxzyniqoS1yU5RClY6783dql1UO4AvxpzpCPYDFIwbEb9zkUo0przhmi4KzyxknB
|
||||
/n/viMWzSnsM9YbakH6KunDTUteme1Dri3Drrq9TUQKCAQAVdvL7YOXPnxFHZbDl
|
||||
7azu5ztcQAfVuxa/1kw/WnwwDDx0hwA13NUK+HNcmUtGbrh/DjwG2x032+UdHUmF
|
||||
qCIN/mHkCoF8BUPLHiB38tw1J3wPNUjm4jQoG96AcYiFVf2d/pbHdo2AHplosHRs
|
||||
go89M+UpELN1h7Ppy4qDuWMME86rtfa7hArqKJFQbdjUVC/wgLkx1tMzJeJLOGfB
|
||||
bgwqiS8jr7CGjsvcgOqfH/qS6iU0glpG98dhTWQaA/OhE9TSzmgQxMW41Qt0eTKr
|
||||
2Bn1pAhxQ2im3Odue6ou9eNqJLiUi6nDqizUjKakj0SeCs71LqIyGZg58OGo2tSn
|
||||
kaOlAoIBAQCE/fO4vQcJpAJOLwLNePmM9bqAcoZ/9auKjPNO8OrEHPTGZMB+Tscu
|
||||
k+wa9a9RgICiyPgcUec8m0+tpjlAGo+EZRdlZqedWUMviCWQC74MKrD/KK9DG3IB
|
||||
ipfkEX2VmiBD2tm1Z3Z+17XlSuLci/iCmzNnM1XP3GYQSRIt/6Lq23vQjzTfU1z7
|
||||
4HwOh23Zb0qjW5NG12sFuS9HQx6kskkY8r2UBlRAggP686Z7W+EkzPSKnYMN6cCo
|
||||
6KkLf3RtlPlDHwq8TUOJlgSLhykbyeCEaDVOkSWhUnU8wJJheS+dMZ5IGbFWZOPA
|
||||
DQ02woOCAdG30ebXSBQL0uB8DL/52sYRAoIBAHtW3NomlxIMqWX8ZYRJIoGharx4
|
||||
ikTOR/jeETb9t//n6kV19c4ICiXOQp062lwEqFvHkKzxKECFhJZuwFc09hVxUXxC
|
||||
LJjvDfauHWFHcrDTWWbd25CNeZ4Sq79GKf+HJ+Ov87WYcjuBFlCh8ES+2N4WZGCn
|
||||
B5oBq1g6E4p1k6xA5eE6VRiHPuFH8N9t1x6IlCZvZBhuVWdDrDd4qMSDEUTlcxSY
|
||||
mtcAIXTPaPcdb3CjdE5a38r59x7dZ/Te2K7FKETffjSmku7BrJITz3iXEk+sn8ex
|
||||
o3mdnFgeQ6/hxvMGgdK2qNb5ER/s0teFjnfnwHuTSXngMDIDb3kLL0ecWlQ=
|
||||
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue