mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add x509_v2 modules
This commit is contained in:
parent
c0791db61f
commit
49a77dbba7
14 changed files with 12392 additions and 0 deletions
|
@ -542,6 +542,7 @@ execution modules
|
|||
winrepo
|
||||
wordpress
|
||||
x509
|
||||
x509_v2
|
||||
xapi_virt
|
||||
xbpspkg
|
||||
xfs
|
||||
|
|
5
doc/ref/modules/all/salt.modules.x509_v2.rst
Normal file
5
doc/ref/modules/all/salt.modules.x509_v2.rst
Normal file
|
@ -0,0 +1,5 @@
|
|||
salt.modules.x509_v2
|
||||
====================
|
||||
|
||||
.. automodule:: salt.modules.x509_v2
|
||||
:members:
|
|
@ -347,6 +347,7 @@ state modules
|
|||
winrepo
|
||||
wordpress
|
||||
x509
|
||||
x509_v2
|
||||
xml
|
||||
xmpp
|
||||
zabbix_action
|
||||
|
|
5
doc/ref/states/all/salt.states.x509_v2.rst
Normal file
5
doc/ref/states/all/salt.states.x509_v2.rst
Normal file
|
@ -0,0 +1,5 @@
|
|||
salt.states.x509_v2
|
||||
===================
|
||||
|
||||
.. automodule:: salt.states.x509_v2
|
||||
:members:
|
|
@ -79,6 +79,8 @@ def __virtual__():
|
|||
"""
|
||||
only load this module if m2crypto is available
|
||||
"""
|
||||
if __opts__.get("x509_v2"):
|
||||
return (False, "Superseded, using x509_v2")
|
||||
if HAS_M2:
|
||||
return __virtualname__
|
||||
else:
|
||||
|
|
1973
salt/modules/x509_v2.py
Normal file
1973
salt/modules/x509_v2.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -190,6 +190,8 @@ def __virtual__():
|
|||
"""
|
||||
only load this module if the corresponding execution module is loaded
|
||||
"""
|
||||
if __opts__.get("x509_v2"):
|
||||
return (False, "Superseded, using x509_v2")
|
||||
if "x509.get_pem_entry" in __salt__:
|
||||
return "x509"
|
||||
else:
|
||||
|
|
1523
salt/states/x509_v2.py
Normal file
1523
salt/states/x509_v2.py
Normal file
File diff suppressed because it is too large
Load diff
1980
salt/utils/x509.py
Normal file
1980
salt/utils/x509.py
Normal file
File diff suppressed because it is too large
Load diff
1310
tests/pytests/functional/modules/test_x509_v2.py
Normal file
1310
tests/pytests/functional/modules/test_x509_v2.py
Normal file
File diff suppressed because it is too large
Load diff
2545
tests/pytests/functional/states/test_x509_v2.py
Normal file
2545
tests/pytests/functional/states/test_x509_v2.py
Normal file
File diff suppressed because it is too large
Load diff
622
tests/pytests/integration/modules/test_x509_v2.py
Normal file
622
tests/pytests/integration/modules/test_x509_v2.py
Normal file
|
@ -0,0 +1,622 @@
|
|||
"""
|
||||
Tests for the Vault module
|
||||
"""
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import logging
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from saltfactories.utils import random_string
|
||||
from saltfactories.utils.tempfiles import temp_file
|
||||
|
||||
import salt.utils.x509 as x509util
|
||||
|
||||
try:
|
||||
import cryptography.x509 as cx509
|
||||
from cryptography.hazmat.primitives.serialization import pkcs7, pkcs12
|
||||
|
||||
HAS_LIBS = True
|
||||
except ImportError:
|
||||
HAS_LIBS = False
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.slow_test,
|
||||
pytest.mark.skipif(HAS_LIBS is False, reason="Needs cryptography library"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_pkidir(tmp_path_factory):
|
||||
_x509_pkidir = tmp_path_factory.mktemp("pki")
|
||||
try:
|
||||
yield _x509_pkidir
|
||||
finally:
|
||||
shutil.rmtree(str(_x509_pkidir), ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def x509_data(
|
||||
x509_pkidir,
|
||||
rsa_privkey,
|
||||
rsa_privkey_enc,
|
||||
rsa_pubkey,
|
||||
csr,
|
||||
):
|
||||
with temp_file("key", rsa_privkey, x509_pkidir) as privkey_file:
|
||||
with temp_file("key_enc", rsa_privkey_enc, x509_pkidir):
|
||||
with temp_file("key_pub", rsa_pubkey, x509_pkidir):
|
||||
with temp_file("csr", csr, x509_pkidir):
|
||||
yield privkey_file
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_master(salt_factories, ca_minion_id, x509_master_config):
|
||||
factory = salt_factories.salt_master_daemon(
|
||||
"x509-master", defaults=x509_master_config
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_minion_id():
|
||||
return random_string("x509ca-minion", uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_minion_id():
|
||||
return random_string("x509-minion", uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_minion_config(x509_minion_id, ca_cert, ca_key, ca_key_enc):
|
||||
return {
|
||||
"open_mode": True,
|
||||
"x509_signing_policies": {
|
||||
"testpolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key,
|
||||
"CN": "from_signing_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testencpolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key_enc,
|
||||
"signing_private_key_passphrase": "correct horse battery staple",
|
||||
"CN": "from_signing_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testmatchpolicy": {
|
||||
"minions": x509_minion_id,
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key,
|
||||
"CN": "from_matching_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testmatchfailpolicy": {
|
||||
"minions": "notallowed",
|
||||
"CN": "from_matchfail_policy",
|
||||
},
|
||||
"testcompoundmatchpolicy": {
|
||||
"minions": "G@testgrain:foo",
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key,
|
||||
"CN": "from_compound_match_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testextpolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key,
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"extendedKeyUsage": None,
|
||||
"subjectKeyIdentifier": "hash",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"issuerAltName": "DNS:salt.ca",
|
||||
"authorityInfoAccess": "OCSP;URI:http://ocsp.salt.ca/",
|
||||
"subjectAltName": "DNS:sub.salt.ca,email:sub@salt.ca",
|
||||
"crlDistributionPoints": "URI:http://salt.ca/myca.crl",
|
||||
"certificatePolicies": "1.2.4.5",
|
||||
"policyConstraints": "requireExplicitPolicy:3",
|
||||
"inhibitAnyPolicy": 2,
|
||||
"nameConstraints": "permitted;IP:192.168.0.0/255.255.0.0,excluded;email:.com",
|
||||
"noCheck": True,
|
||||
"tlsfeature": "status_request",
|
||||
},
|
||||
},
|
||||
"x509_v2": True,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def x509ca_salt_minion(x509_salt_master, ca_minion_id, ca_minion_config):
|
||||
assert x509_salt_master.is_running()
|
||||
factory = x509_salt_master.salt_minion_daemon(
|
||||
ca_minion_id,
|
||||
defaults=ca_minion_config,
|
||||
)
|
||||
with factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = factory.salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.returncode == 0, ret
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_minion(x509_salt_master, x509_minion_id):
|
||||
assert x509_salt_master.is_running()
|
||||
factory = x509_salt_master.salt_minion_daemon(
|
||||
x509_minion_id,
|
||||
defaults={"open_mode": True, "x509_v2": True, "grains": {"testgrain": "foo"}},
|
||||
)
|
||||
with factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = factory.salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.returncode == 0, ret
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_master_config(ca_minion_id):
|
||||
return {
|
||||
"open_mode": True,
|
||||
"peer": {
|
||||
".*": [
|
||||
"x509.sign_remote_certificate",
|
||||
],
|
||||
ca_minion_id: [
|
||||
"match.compound",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_privkey():
|
||||
return """\
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAzIdEbSkbPIc5F/aewNoqWPsF/YP+DByMwvYs+0K+lehc39P8
|
||||
2fL8K2GIaGMBBzqlsX6CplAzGcoEQEBLTouLm+JYC5e1zRjaml4M+Bid8A7qwdjl
|
||||
Wd0enCAxVB9BMNnj/mokWzh3hAQMBXfmddGRhH0P9KXfjBNh2V09vfHdtS9XMEEQ
|
||||
jN6vCxaezXqsOMN3bjRTIcUatH7dVUgUpt9cye1mdbD5KVBgJ9MArc2tJ3rmB0lx
|
||||
jEbAhTEHrNnIkDOJCKE8TaQOW4RyVWlIvSEL+Ov0TPeXXaef8HJlkyIpKrCZ+c4i
|
||||
0N7qOlyrJEWTXmKNCj87xgTpY5I7ARISeOQD8QIDAQABAoIBABYNN4l1dyRNiBBX
|
||||
XMJ6QzqYxgqRYqC3q02R8UOd7KKJDQps9sQg+KNMvsJSelfnMNo0Q63e08OiDldH
|
||||
F1d+oCzMeKW3U7irR1aBcXCGZvDtCs6frgrEVnqK1ga13/d+ZqCVnRngurIXJZyp
|
||||
UsW9NK1ONpwwDiwyIsimzvNd0oOoR6ROIN2Fk+AhKQ6bPdgqLM1Swx6BA0J/aaqO
|
||||
jAqSkYkGOEL970W8ZhnyyDDRcbgPbacUDo7AJnrBeqHoAqrJ1PzJ3jhcWDJl8Xcy
|
||||
uVDP1hBeK9yg4nuMcArsqrRQvqL2GuafGYygfzrU1aW96hlXciOv32ov36h2qIJU
|
||||
r4JfJGECgYEA7UPD4iRsHV6eMkD98Ev74ygdnFL2TMknqOUEboPNiQzSzr5oVrKa
|
||||
KFDhzenUNlMSoeiAaLLI7xaD4xptXuN8xx7sQZVSiEniBfJ7F+9sPNjCXwYbUuWp
|
||||
qpp6KfCrjLxDxgSKH9FUIlTvL7M4lmAD2yHn4zXjFz3BOs261JUn6l0CgYEA3K2/
|
||||
S2eP3VUL6K4+HNMzXTj9Q8S7LSYnTZVIjfek6pQHMwaMKE8EC7L4XeS9TZ49BKCS
|
||||
Mh9RI2yBCX6L1uo2zURAI0oDrowDhjaUCD4xxTD27OyMcvjdSzk/+0E+DtsWdgYm
|
||||
FGX/l0zTRUsZBbc7ItTG0ksIB+aMM4njBbHubqUCgYAq9llS6pt1Gfv1R5Vz3J5o
|
||||
vIvYEaGtt8Lpr0aFKHKgPWUysIG+KSsG39ZzbcLSb2pxTONrkewWdvI8vj1NsE2Y
|
||||
1L2dBofiS9aUkxq888qanflcMYPjF9kIHl6+l2jI3BI9mfbU2hes+8ovzfkSKaKp
|
||||
HFOb7dcID1Oc7UHGWpfWtQKBgQDC3Y4xOKbaLDJS6iIg9ALETAGgqQUbzjggkzU5
|
||||
X7e6CLL+xMZZBcUty4Dz8HuVIakCAAR4zByq6jJbvuofAj0YLy9vufjcVfj6uBEp
|
||||
4jmyxhUVi6BOGiHXPhuYc7koByCjYbSYiKUU5psc8j6LRIysqjVTFzxlNZkSHa1h
|
||||
pwhDnQKBgATpQou7MeAOMHjMPaNx8OCq7QNhocp8Q+goxPb0ND2jF9xSI+gjzRRt
|
||||
Kpz+xO6tri6wCgWrmE5cJbEe3/EYf3bmbNA9wOQ72kfoy9uO0cCi+5gSJigwaIKM
|
||||
DYRTDIS9eg2LF4B64hZvkCLTmP4rLJWdRnWrLosIC4rD1uWgGayC
|
||||
-----END RSA PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_privkey_enc():
|
||||
return """\
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIHU2H6hhL0gYCAggA
|
||||
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBD64PydhZIJPW9amw7M8yGvBIIE
|
||||
0LHXvvQleCJMlH/Rtml1Vx2nygReVl+1Ag+FjtsNQHtsXYkzVWSDI0zI7nFyDpb9
|
||||
Kr2+9UOsOhQA5/swka9ude4oJng0YZcV4qgar8yFncWTrMTk/mrvFSNZPz9LMGsq
|
||||
in7hzYGAP6XdprHgJfw+wDQfwbwcTQp5DUOPYbhxfnggVQBL84gp/2urCcNnFX+T
|
||||
OKGm9C3NfLycrCbaQxaV/2oTo7+UHUaXKwZwY6zKxCqbwGBy7dNcZD16nJyOBmbj
|
||||
ytOi/OqBcoj03yK4ETIm7EWwem6CRAbPH1GnUAxmb5tG6jzKphbMJur8n72Vv+VK
|
||||
9+Gkz5vOq1O1wlK+DfB+Xrgfx3lHHQllxi7FtlQegSFlIbHAacG/muwMRQ5PoMEp
|
||||
RaGQkxOhiU7VSaZ3Gdx3TrQMaF5nBqvs90Xw40uWdD9+Kd3Oqkj9OgiqHZwgWPfW
|
||||
txB+jXYGj1ERUvb36T7P8IH/QDa8jwVf3+f1pOpoMe4+6i3rr9bAkDhIjpNDo2a0
|
||||
YXvVns18UisnLXHxdAZb9R2V/VoTxhs3IqK3nEb5qnb1RAtJfV4p1ENVsoPiHl5C
|
||||
pq7xcRO+25hy18CjMWqj8t3PH5MdBL8UMFZyDnIH9z9N019U0ZIaD3NqiiRgGD+U
|
||||
CSLkoXq5oni5RkDQCnzJRFo/Vzmx2P5OJyZvHYLtVOUwsp1dW8JFtdKJoGBxNc1M
|
||||
kc7eevfwUZEDc2dHxcwxDj0Tas05DaMBib3Oi0D/ipxDdzW+uENQHdCwy7XZf+T+
|
||||
ig03Ega0/w+c/rdnUevdXK/L1sIO7F8hyDlVG1q0PeoJ8jXnZk+UfNYy820sPWIE
|
||||
IwtT1aODvnYgio8vgrDXpB0qVDNi2Ml83gYxznIQuxWg6dCrifvCa8TwCTe9tAhv
|
||||
gTkEkYdyBTpvT585z/1x+dra3uOGiMCN0rP3n3JaICDqCwImznvIP8kqNEnalWQj
|
||||
pUVI3nKZunTtrL9vAegW9jF0Ipvyf+VSQmw+yN5B35Qfy95CwAwtJ/HPjy1sZmJZ
|
||||
carKrlqoD4xdSyrIun3fraGTbM+u4S+USRjikce+pu1cHi70Y3xm4JBAZsRJgPwB
|
||||
G/Orf5yC+E2pCK+7rX3rWINgwmX/kk94EtnYbMeES+lhlKOu/mR09K00atuBEDnJ
|
||||
o0MCM0BWYy5XQ2RAJLKCdcuJ2aWs/+slKRzlTCWnCUgISng6KFpcyA0aS/8r3ZyH
|
||||
SKdoSSgOtAieE/TGll0wjvONMIMfoEgR40OBV8BCSF8zWASZBXASTTSlUcu2wQ0q
|
||||
/wPFS2KkBdBc+qr+TxDNoeFDX+Rh9Nai25O/xoRtCC7afHsd5aQ4yen5C34/jsR1
|
||||
2kuayvZJ2pgYfIobFdgq9qHi637dVeW8n09XRq6HWhZu1ODO5bGX2oLr64MJAmgi
|
||||
fA+zu5Dfoe2Q4N1Ja3y0M7Xpfws14jyFxnJ8dR/T6rIJOy1QtHGo3UTai8nSBqCP
|
||||
RJ766EKBW7j83/53aYyChHvTXEPf4C29iOur72iMAlT2S06K/SH4fFM3brBzz0Fq
|
||||
EykXIgConLXDwj9+87XKYmOQX/0UP2sxAno6gJakdzExIod+u5koXP1o9vL5zMlH
|
||||
ahZPgPpP2p2uAz1+9MHpVPo2EIrvibm5T89DznwuaEfe
|
||||
-----END ENCRYPTED PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_pubkey():
|
||||
return """\
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzIdEbSkbPIc5F/aewNoq
|
||||
WPsF/YP+DByMwvYs+0K+lehc39P82fL8K2GIaGMBBzqlsX6CplAzGcoEQEBLTouL
|
||||
m+JYC5e1zRjaml4M+Bid8A7qwdjlWd0enCAxVB9BMNnj/mokWzh3hAQMBXfmddGR
|
||||
hH0P9KXfjBNh2V09vfHdtS9XMEEQjN6vCxaezXqsOMN3bjRTIcUatH7dVUgUpt9c
|
||||
ye1mdbD5KVBgJ9MArc2tJ3rmB0lxjEbAhTEHrNnIkDOJCKE8TaQOW4RyVWlIvSEL
|
||||
+Ov0TPeXXaef8HJlkyIpKrCZ+c4i0N7qOlyrJEWTXmKNCj87xgTpY5I7ARISeOQD
|
||||
8QIDAQAB
|
||||
-----END PUBLIC KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def csr():
|
||||
return """\
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICRTCCAS0CAQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyH
|
||||
RG0pGzyHORf2nsDaKlj7Bf2D/gwcjML2LPtCvpXoXN/T/Nny/CthiGhjAQc6pbF+
|
||||
gqZQMxnKBEBAS06Li5viWAuXtc0Y2ppeDPgYnfAO6sHY5VndHpwgMVQfQTDZ4/5q
|
||||
JFs4d4QEDAV35nXRkYR9D/Sl34wTYdldPb3x3bUvVzBBEIzerwsWns16rDjDd240
|
||||
UyHFGrR+3VVIFKbfXMntZnWw+SlQYCfTAK3NrSd65gdJcYxGwIUxB6zZyJAziQih
|
||||
PE2kDluEclVpSL0hC/jr9Ez3l12nn/ByZZMiKSqwmfnOItDe6jpcqyRFk15ijQo/
|
||||
O8YE6WOSOwESEnjkA/ECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQB9PbGDorNt
|
||||
Tl4xYObUsQwUkMVRPI59MLLYKEJRu/DGSA4sKf/vLK1ypyLIvxNp4gNFgm28nDV2
|
||||
t2gQ+DpBvwC1+XZQDZjgL7pPtLvErGCs6O6Y5fW8Lywxx5GqiVTIic/XLKTijKJv
|
||||
EecvwPjWv1VgtBKLZxN18KgIIs2Sq/t+GYe+Lu30c92Lc5INbrwTIEDYNTHywKet
|
||||
8FTSaYEMU6sGgsrIC5VxNT00EgJHjyjdCVIqQr/LqKyBMqJICWUSPq2ufjwqFsFi
|
||||
q1HXd62bA8k27ukX7w8qWsk6fOTwPh5F3883L5jVqcRsL9pqb4RUugTh/aReVlKW
|
||||
0WMDRBksXs1E
|
||||
-----END CERTIFICATE REQUEST-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_cert():
|
||||
# the final newline here is important since it is compared
|
||||
# with the ca_server return, which is parsed to contain one
|
||||
return """\
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDODCCAiCgAwIBAgIIbfpgqP0VGPgwDQYJKoZIhvcNAQELBQAwKzELMAkGA1UE
|
||||
BhMCVVMxDTALBgNVBAMMBFRlc3QxDTALBgNVBAoMBFNhbHQwHhcNMjIxMTE1MTQw
|
||||
NDMzWhcNMzIxMTEyMTQwNDMzWjArMQswCQYDVQQGEwJVUzENMAsGA1UEAwwEVGVz
|
||||
dDENMAsGA1UECgwEU2FsdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AOGTScvrjcEt6vsJcG9RUp6fKaDNDWZnJET0omanK9ZwaoGpJPp8UDYe/8ADeI7N
|
||||
10wdyB4oDM9gRDjInBtdQO/PsrmKZF6LzqVFgLMxu2up+PHMi9z6B2P4esIAzMu9
|
||||
PYxc9zH4HzLImHqscVD2HCabsjp9X134Af7hVY5NN/W/4qTP7uOM20wSG2TPI6+B
|
||||
tA9VyPbEPMPRzXzrqc45rVYe6kb2bT84GE93Vcu/e5JZ/k2AKD8Hoa2cxLPsTLq5
|
||||
igl+D+k+dfUtiABiKPvVQiYBsD1fyHDn2m7B6pCgvrGqHjsoAKufgFnXy6PJRg7n
|
||||
vQfaxSiusM5s+VS+fjlvgwsCAwEAAaNgMF4wDwYDVR0TBAgwBgEB/wIBATALBgNV
|
||||
HQ8EBAMCAQYwHQYDVR0OBBYEFFzy8fRTKSOe7kBakqO0Ki71potnMB8GA1UdIwQY
|
||||
MBaAFFzy8fRTKSOe7kBakqO0Ki71potnMA0GCSqGSIb3DQEBCwUAA4IBAQBZS4MP
|
||||
fXYPoGZ66seM+0eikScZHirbRe8vHxHkujnTBUjQITKm86WeQgeBCD2pobgBGZtt
|
||||
5YFozM4cERqY7/1BdemUxFvPmMFFznt0TM5w+DfGWVK8un6SYwHnmBbnkWgX4Srm
|
||||
GsL0HHWxVXkGnFGFk6Sbo3vnN7CpkpQTWFqeQQ5rHOw91pt7KnNZwc6I3ZjrCUHJ
|
||||
+UmKKrga16a4Q+8FBpYdphQU609npo/0zuaE6FyiJYlW3tG+mlbbNgzY/+eUaxt2
|
||||
9Bp9mtA+Hkox551Mfpq45Oi+ehwMt0xjZCjuFCM78oiUdHCGO+EmcT7ogiYALiOF
|
||||
LN1w5sybsYwIw6QN
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_key():
|
||||
return """\
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4ZNJy+uNwS3q+wlwb1FSnp8poM0NZmckRPSiZqcr1nBqgakk
|
||||
+nxQNh7/wAN4js3XTB3IHigMz2BEOMicG11A78+yuYpkXovOpUWAszG7a6n48cyL
|
||||
3PoHY/h6wgDMy709jFz3MfgfMsiYeqxxUPYcJpuyOn1fXfgB/uFVjk039b/ipM/u
|
||||
44zbTBIbZM8jr4G0D1XI9sQ8w9HNfOupzjmtVh7qRvZtPzgYT3dVy797kln+TYAo
|
||||
PwehrZzEs+xMurmKCX4P6T519S2IAGIo+9VCJgGwPV/IcOfabsHqkKC+saoeOygA
|
||||
q5+AWdfLo8lGDue9B9rFKK6wzmz5VL5+OW+DCwIDAQABAoIBAFfImc9hu6iR1gAb
|
||||
jEXFwAE6r1iEc9KGEPdEvG52X/jzhn8u89UGy7BEIAL5VtE8Caz1agtSSqnpLKNs
|
||||
blO31q18hnDuCmFAxwpKIeuaTvV3EAoJL+Su6HFfIWaeKRSgcHNPOmOXy4xXw/75
|
||||
XJ/FJu9fZ9ybLaHEAgLObh0Sr9RSPQbZ72ZawPP8+5WCbR+2w90RApHXQL0piSbW
|
||||
lIx1NE6o5wQb3vik8z/k5FqLCY2a8++WNyfvS+WWFY5WXGI7ZiDDQk46gnslquH2
|
||||
Lon5CEn3JlTGQFhxaaa2ivssscf2lA2Rvm2E8o1rdZJS2OpSE0ai4TXY9XnyjZj1
|
||||
5usWIwECgYEA+3Mwu03A7PyLEBksS/u3MSo/176S9lF/uXcecQNdhAIalUZ8AgV3
|
||||
7HP2yI9ZC0ekA809ZzFjGFostXm9VfUOEZ549jLOMzvBtCdaI0aBUE8icu52fX4r
|
||||
fT2NY6hYgz5/fxD8sq1XH/fqNNexABwtViH6YAly/9A1/8M3BOWt72UCgYEA5ag8
|
||||
sIfiBUoWd1sS6qHDuugWlpx4ZWYC/59XEJyCN2wioP8qFji/aNZxF1wLfyQe/zaa
|
||||
YBFusjsBnSfBU1p4UKCRHWQ9/CnC0DzqTkyKC4Fv8GuxgywNm5W9gPKk7idHP7mw
|
||||
e+7Uvf1pOQccqEPh7yltpW+Xw27gfsC2DMAIGa8CgYByv/q5P56PiCCeVB6W/mR3
|
||||
l2RTPLEsn7y+EtJdmL+QgrVG8kedVImJ6tHwbRqhvyvmYD9pXGxwrJZCqy/wjkjB
|
||||
WaSyFjVrxBV99Yd5Ga/hyntaH+ELHA0UtoZTuHvMSTU9866ei+R6vlSvkM9B0ZoO
|
||||
+KqeMTG99HLwKVJudbKO0QKBgQCd33U49XBOqoufKSBr4yAmUH2Ws6GgMuxExUiY
|
||||
xr5NUyzK+B36gLA0ZZYAtOnCURZt4x9kgxdRtnZ5jma74ilrY7XeOpbRzfN6KyX3
|
||||
BW6wUh6da6rvvUztc5Z+Gk9+18mG6SOFTr04jgfTiCwPD/s06YnSfFAbrRDukZOU
|
||||
WD45SQKBgBvjSwl3AbPoJnRjZjGuCUMKQKrLm30xCeorxasu+di/4YV5Yd8VUjaO
|
||||
mYyqXW6bQndKLuXT+AXtCd/Xt2sI96z8mc0G5fImDUxQjMUuS3RyQK357cEOu8Zy
|
||||
HdI7Pfaf/l0HozAw/Al+LXbpmSBdfmz0U/EGAKRqXMW5+vQ7XHXD
|
||||
-----END RSA PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_key_enc():
|
||||
return """\
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIy/O+FhcKBKUCAggA
|
||||
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDtSfZzKh7brkHFw/s6bcbVBIIE
|
||||
0JcLyycDhdSPzL7Zm1+ZLavjxiuaGEaHU8hu8ZScqyjcdWbdOfOuqZgu7OzxwfIc
|
||||
8Q1bfqMGUfxPcs/JQh13CVOaDYmafeMZYN3rqsNoci11iaHDhTAqgYCM2iVXaFUt
|
||||
6ZdfW+/hEk+yHwK5K2R1/ks8buAe0OgjkV0N3DqAif93BPyFP6XT7btVMrorGJjh
|
||||
1OJjuw3q0xJ02rn7O5imaZ5NnCIDShkKwWO6sUew3QHhW61/nuCBPyJTsAO0L4+t
|
||||
9zjb2jOIIuvTpZUhAty6I+bKgaYLhsii7z5jVYpt+NbYpzIe+9RvAD1psGk9+bGD
|
||||
rN70Bnhx29mPEKdmozXVQ8GTqDOSQSYMr9aax+BhSJoTnCtVtGGX0LXE5Dvd/HHy
|
||||
+Yw2HFrVglptsPYo4EBKccC3FJlS0mL6yBW5NCpU7MOhDV/iOMbzM4bqwKG+jqaw
|
||||
sjIScCg+ljBxGhNrcMa0AEBWukTRe4gERpb8AyGKYOSVN6iZyP5qhN/Abu1asKrj
|
||||
c4NRUu3yILleZuxjkDd4w0CwhjlCaKFLsp1XeFE5ZHM5Iezi1/I4QMXFTydB1KnX
|
||||
xOSofZ7b7pnvOiBQG2nQzYSjSnBO7E7NQOhjvkRgcxNsdAQWADIqdE3bKZ8qcEZ6
|
||||
q1TE0XtcDgwFGwQF/cyuEEXyMAkQV687e8IdCjc+MbyyqUtQA9382JyjOuzavvMD
|
||||
nO5s80lB5aa0WHdE+Rg7KiBIwL1CjBSGSiggKvkG01ObeQL4DCQG6gHgz+nvdiNe
|
||||
du2u6hW2/PUuUIOM2ApE98T2TAzCnyu02iMIN5aH4za5y1w5YzaU4Lsl4nzAEA3c
|
||||
8EuVIWMutZnqT4ZSCLCq1AtDYkSXxIjGQPwhRslyCJuwtuiaDXLIZIpMRGqMKdGS
|
||||
c3q0k5ba92jXppIOVYN/kViNjYeHVZ3KRAi2MqUByqiMBkZo11NsgaU/uPsKsK16
|
||||
D0XueVs9EobU55tgBV71Q8g/5BiGG19W5UZVzjiiuGuj44msOfYV4027KqqFf302
|
||||
U5RXAwBko9S+v3SuTZrRXK4uuYceR9Uyco8aP/tNAhHEGa8Z73vLngZICp57qD1h
|
||||
8smjOrm1volZpu31HP9CWVh47GyuzSZ8BUFrR/uXfa+uqyLqeBKglz5SC6Ak3nL8
|
||||
eAHu3EK2dVp4vqwYB2oO9DQqs4CN7DKyArNeUzKSf6ZKEYBZCdF5V5HgbSpY5f+e
|
||||
xj5cpuMVc7s+Nxv/0bqxNzt8ghe2sDELxK8lo7Q6E+aUNBWt++nHI2b8y5ynaANU
|
||||
kQjeoorrPHUScXN8TVrgrIYIfXOqkI14UmroRH5/oyORHXN25JekV1DisKZOtSdV
|
||||
Vqt3o/hlGFYhaeznIgquBm27trLkLHOfCGx6M2xlKszlWBP03zFLp0PiXE+y07zC
|
||||
IwzaiVlj/O+QIsiMmrtc8WXYiNWVN5XDe1elFPs1K2cw0cIeyLgC1Bibxa7dH01G
|
||||
Z0Nr+hZN+/EqI3Tu+lWeWtj/lIhjJrKQvUOMM4W1MFZZdK09ZsCdW0Y1fFYn/3Xz
|
||||
g1KvGcFoszp0uMptlJUhsxtFooG4xKtgEITmtraRU+hTGU3NZgtk7Qff4tFa0O0h
|
||||
A62orBDc+8x+AehfwYSm11dz5/P6aL3QZf+tzr05vbVn
|
||||
-----END ENCRYPTED PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cert_args(ca_minion_id, x509_data):
|
||||
return {
|
||||
"ca_server": ca_minion_id,
|
||||
"signing_policy": "testpolicy",
|
||||
"private_key": str(x509_data),
|
||||
"CA": "from_args",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cert_args_exts():
|
||||
return {
|
||||
"basicConstraints": "critical, CA:TRUE, pathlen:1",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign, digitalSignature",
|
||||
"extendedKeyUsage": "OCSPSigning",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"issuerAltName": "DNS:mysalt.ca",
|
||||
"authorityInfoAccess": "OCSP;URI:http://ocsp.salt.ca/",
|
||||
"subjectAltName": "DNS:me.salt.ca",
|
||||
"crlDistributionPoints": None,
|
||||
"certificatePolicies": "1.2.4.5",
|
||||
"policyConstraints": "requireExplicitPolicy:3",
|
||||
"inhibitAnyPolicy": 2,
|
||||
"nameConstraints": "permitted;IP:192.168.0.0/255.255.0.0,excluded;email:.com",
|
||||
"noCheck": True,
|
||||
"tlsfeature": "status_request",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_run_cli(x509_salt_master):
|
||||
return x509_salt_master.salt_run_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_call_cli(x509_salt_minion):
|
||||
return x509_salt_minion.salt_call_cli()
|
||||
|
||||
|
||||
def test_sign_remote_certificate(x509_salt_call_cli, cert_args, ca_key, rsa_privkey):
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_match(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["signing_policy"] = "testmatchpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_matching_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_compound_match(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["signing_policy"] = "testcompoundmatchpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_compound_match_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_enc(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["private_key"] += "_enc"
|
||||
cert_args["private_key_passphrase"] = "hunter2"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_ca_enc(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["signing_policy"] = "testencpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_pubkey(
|
||||
x509_salt_call_cli, cert_args, x509_data, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args.pop("private_key")
|
||||
cert_args["public_key"] = str(x509_data.parent / "key_pub")
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_csr(
|
||||
x509_salt_call_cli, cert_args, x509_data, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args.pop("private_key")
|
||||
cert_args["csr"] = str(x509_data.parent / "csr")
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_nonexistent_policy(x509_salt_call_cli, cert_args):
|
||||
cert_args["signing_policy"] = "missingpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert not ret.data
|
||||
assert "signing_policy must be specified and defined" in ret.stderr
|
||||
|
||||
|
||||
def test_sign_remote_certificate_disallowed_policy(x509_salt_call_cli, cert_args):
|
||||
cert_args["signing_policy"] = "testmatchfailpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert not ret.data
|
||||
assert "minion not permitted to use specified signing policy" in ret.stderr
|
||||
|
||||
|
||||
def test_get_signing_policy_remote(x509_salt_call_cli, cert_args, ca_minion_config):
|
||||
testpolicy = copy.deepcopy(
|
||||
ca_minion_config["x509_signing_policies"]["testencpolicy"]
|
||||
)
|
||||
testpolicy.pop("signing_private_key", None)
|
||||
testpolicy.pop("signing_private_key_passphrase", None)
|
||||
ret = x509_salt_call_cli.run(
|
||||
"x509.get_signing_policy", "testencpolicy", ca_server=cert_args["ca_server"]
|
||||
)
|
||||
assert ret.data
|
||||
assert ret.data == testpolicy
|
||||
|
||||
|
||||
def test_sign_remote_certificate_ext_override(
|
||||
x509_salt_call_cli, cert_args, cert_args_exts
|
||||
):
|
||||
cert_args.update(cert_args_exts)
|
||||
cert_args["signing_policy"] = "testextpolicy"
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert (
|
||||
cert.extensions.get_extension_for_class(cx509.BasicConstraints).value.ca
|
||||
is False
|
||||
)
|
||||
assert (
|
||||
cert.extensions.get_extension_for_class(cx509.KeyUsage).value.digital_signature
|
||||
is False
|
||||
)
|
||||
with pytest.raises(cx509.ExtensionNotFound):
|
||||
cert.extensions.get_extension_for_class(cx509.ExtendedKeyUsage)
|
||||
assert (
|
||||
cert.extensions.get_extension_for_class(
|
||||
cx509.IssuerAlternativeName
|
||||
).value.get_values_for_type(cx509.DNSName)[0]
|
||||
== "salt.ca"
|
||||
)
|
||||
assert (
|
||||
cert.extensions.get_extension_for_class(
|
||||
cx509.SubjectAlternativeName
|
||||
).value.get_values_for_type(cx509.DNSName)[0]
|
||||
== "sub.salt.ca"
|
||||
)
|
||||
|
||||
|
||||
def test_sign_remote_certificate_copypath(x509_salt_call_cli, cert_args, tmp_path):
|
||||
cert_args["copypath"] = str(tmp_path)
|
||||
ret = x509_salt_call_cli.run("x509.create_certificate", **cert_args)
|
||||
assert ret.data
|
||||
cert = _get_cert(ret.data)
|
||||
assert (tmp_path / f"{cert.serial_number:x}.crt").exists()
|
||||
|
||||
|
||||
def _belongs_to(cert_or_pubkey, privkey):
|
||||
if isinstance(cert_or_pubkey, cx509.Certificate):
|
||||
cert_or_pubkey = cert_or_pubkey.public_key()
|
||||
return x509util.is_pair(cert_or_pubkey, x509util.load_privkey(privkey))
|
||||
|
||||
|
||||
def _signed_by(cert, privkey):
|
||||
return x509util.verify_signature(cert, x509util.load_privkey(privkey).public_key())
|
||||
|
||||
|
||||
def _get_cert(cert, encoding="pem", passphrase=None):
|
||||
try:
|
||||
p = Path(cert)
|
||||
if p.exists():
|
||||
cert = p.read_bytes()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
|
||||
if "pem" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = cert.encode()
|
||||
return cx509.load_pem_x509_certificate(cert)
|
||||
if "der" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
return cx509.load_der_x509_certificate(cert)
|
||||
if "pkcs7_pem" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = cert.encode()
|
||||
return pkcs7.load_pem_pkcs7_certificates(cert)
|
||||
if "pkcs7_der" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
return pkcs7.load_der_pkcs7_certificates(cert)
|
||||
if "pkcs12" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
if passphrase is not None and not isinstance(passphrase, bytes):
|
||||
passphrase = passphrase.encode()
|
||||
return pkcs12.load_pkcs12(cert, passphrase)
|
707
tests/pytests/integration/states/test_x509_v2.py
Normal file
707
tests/pytests/integration/states/test_x509_v2.py
Normal file
|
@ -0,0 +1,707 @@
|
|||
"""
|
||||
Tests for the Vault module
|
||||
"""
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from saltfactories.utils import random_string
|
||||
from saltfactories.utils.tempfiles import temp_file
|
||||
|
||||
import salt.utils.x509 as x509util
|
||||
|
||||
try:
|
||||
import cryptography
|
||||
import cryptography.x509 as cx509
|
||||
from cryptography.hazmat.primitives.serialization import (
|
||||
load_der_private_key,
|
||||
load_pem_private_key,
|
||||
pkcs7,
|
||||
pkcs12,
|
||||
)
|
||||
|
||||
HAS_LIBS = True
|
||||
except ImportError:
|
||||
HAS_LIBS = False
|
||||
|
||||
CRYPTOGRAPHY_VERSION = tuple(int(x) for x in cryptography.__version__.split("."))
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.slow_test,
|
||||
pytest.mark.skipif(HAS_LIBS is False, reason="Needs cryptography library"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_pkidir(tmp_path_factory):
|
||||
_x509_pkidir = tmp_path_factory.mktemp("pki")
|
||||
try:
|
||||
yield _x509_pkidir
|
||||
finally:
|
||||
shutil.rmtree(str(_x509_pkidir), ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def x509_data(
|
||||
x509_pkidir,
|
||||
rsa_privkey,
|
||||
rsa_privkey_enc,
|
||||
rsa_pubkey,
|
||||
csr,
|
||||
):
|
||||
with temp_file("key", rsa_privkey, x509_pkidir):
|
||||
with temp_file("key_enc", rsa_privkey_enc, x509_pkidir):
|
||||
with temp_file("key_pub", rsa_pubkey, x509_pkidir):
|
||||
with temp_file("csr", csr, x509_pkidir):
|
||||
yield x509_pkidir
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_master(salt_factories, ca_minion_id, x509_master_config):
|
||||
factory = salt_factories.salt_master_daemon(
|
||||
"x509-master", defaults=x509_master_config
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_minion_id():
|
||||
return random_string("x509ca-minion", uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_minion_id():
|
||||
return random_string("x509-minion", uppercase=False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_minion_config(x509_minion_id, ca_cert, ca_key_enc, rsa_privkey, ca_new_cert):
|
||||
return {
|
||||
"open_mode": True,
|
||||
"x509_signing_policies": {
|
||||
"testpolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key_enc,
|
||||
"signing_private_key_passphrase": "correct horse battery staple",
|
||||
"CN": "from_signing_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testchangepolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key_enc,
|
||||
"signing_private_key_passphrase": "correct horse battery staple",
|
||||
"CN": "from_changed_signing_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testchangecapolicy": {
|
||||
"signing_cert": ca_new_cert,
|
||||
"signing_private_key": rsa_privkey,
|
||||
"CN": "from_signing_policy",
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
},
|
||||
"testextpolicy": {
|
||||
"signing_cert": ca_cert,
|
||||
"signing_private_key": ca_key,
|
||||
"basicConstraints": "critical, CA:FALSE",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign",
|
||||
"extendedKeyUsage": None,
|
||||
"subjectKeyIdentifier": "hash",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"issuerAltName": "DNS:salt.ca",
|
||||
"authorityInfoAccess": "OCSP;URI:http://ocsp.salt.ca/",
|
||||
"subjectAltName": "DNS:sub.salt.ca,email:sub@salt.ca",
|
||||
"crlDistributionPoints": "URI:http://salt.ca/myca.crl",
|
||||
"certificatePolicies": "1.2.4.5",
|
||||
"policyConstraints": "requireExplicitPolicy:3",
|
||||
"inhibitAnyPolicy": 2,
|
||||
"nameConstraints": "permitted;IP:192.168.0.0/255.255.0.0,excluded;email:.com",
|
||||
"noCheck": True,
|
||||
"tlsfeature": "status_request",
|
||||
},
|
||||
},
|
||||
"x509_v2": True,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def x509ca_salt_minion(x509_salt_master, ca_minion_id, ca_minion_config):
|
||||
assert x509_salt_master.is_running()
|
||||
factory = x509_salt_master.salt_minion_daemon(
|
||||
ca_minion_id,
|
||||
defaults=ca_minion_config,
|
||||
)
|
||||
with factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = factory.salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.returncode == 0, ret
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_minion(x509_salt_master, x509_minion_id):
|
||||
assert x509_salt_master.is_running()
|
||||
factory = x509_salt_master.salt_minion_daemon(
|
||||
x509_minion_id,
|
||||
defaults={"open_mode": True, "x509_v2": True, "grains": {"testgrain": "foo"}},
|
||||
)
|
||||
with factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = factory.salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.returncode == 0, ret
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_master_config(ca_minion_id):
|
||||
return {
|
||||
"open_mode": True,
|
||||
"peer": {
|
||||
".*": [
|
||||
"x509.sign_remote_certificate",
|
||||
],
|
||||
ca_minion_id: [
|
||||
"match.compound",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def privkey_new(x509_salt_master, tmp_path, ca_minion_id, x509_salt_call_cli):
|
||||
state = f"""\
|
||||
Private key:
|
||||
x509.private_key_managed:
|
||||
- name: {tmp_path}/priv.key
|
||||
- algo: ec
|
||||
- backup: true
|
||||
- new: true
|
||||
{{% if salt['file.file_exists']('{tmp_path}/priv.key') -%}}
|
||||
- prereq:
|
||||
- x509: {tmp_path}/cert.pem
|
||||
{{%- endif %}}
|
||||
|
||||
Certificate:
|
||||
x509.certificate_managed:
|
||||
- name: {tmp_path}/cert.pem
|
||||
- ca_server: {ca_minion_id}
|
||||
- signing_policy: testpolicy
|
||||
- private_key: {tmp_path}/priv.key
|
||||
- days_remaining: 999
|
||||
- backup: true
|
||||
"""
|
||||
with x509_salt_master.state_tree.base.temp_file("manage_cert.sls", state):
|
||||
ret = x509_salt_call_cli.run("state.apply", "manage_cert")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"]
|
||||
assert (tmp_path / "priv.key").exists()
|
||||
assert (tmp_path / "cert.pem").exists()
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def privkey_new_pkcs12(x509_salt_master, tmp_path, ca_minion_id, x509_salt_call_cli):
|
||||
state = f"""\
|
||||
Private key:
|
||||
x509.private_key_managed:
|
||||
- name: {tmp_path}/cert
|
||||
- algo: ec
|
||||
- backup: true
|
||||
- new: true
|
||||
- encoding: pkcs12
|
||||
{{% if salt['file.file_exists']('{tmp_path}/priv.key') -%}}
|
||||
- prereq:
|
||||
- x509: {tmp_path}/cert.pem
|
||||
{{%- endif %}}
|
||||
|
||||
Certificate:
|
||||
x509.certificate_managed:
|
||||
- name: {tmp_path}/cert
|
||||
- ca_server: {ca_minion_id}
|
||||
- signing_policy: testpolicy
|
||||
- private_key: {tmp_path}/cert
|
||||
- days_remaining: 999
|
||||
- backup: true
|
||||
- encoding: pkcs12
|
||||
"""
|
||||
with x509_salt_master.state_tree.base.temp_file("manage_cert.sls", state):
|
||||
ret = x509_salt_call_cli.run("state.apply", "manage_cert")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"]
|
||||
assert (tmp_path / "cert").exists()
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_privkey():
|
||||
return """\
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAzIdEbSkbPIc5F/aewNoqWPsF/YP+DByMwvYs+0K+lehc39P8
|
||||
2fL8K2GIaGMBBzqlsX6CplAzGcoEQEBLTouLm+JYC5e1zRjaml4M+Bid8A7qwdjl
|
||||
Wd0enCAxVB9BMNnj/mokWzh3hAQMBXfmddGRhH0P9KXfjBNh2V09vfHdtS9XMEEQ
|
||||
jN6vCxaezXqsOMN3bjRTIcUatH7dVUgUpt9cye1mdbD5KVBgJ9MArc2tJ3rmB0lx
|
||||
jEbAhTEHrNnIkDOJCKE8TaQOW4RyVWlIvSEL+Ov0TPeXXaef8HJlkyIpKrCZ+c4i
|
||||
0N7qOlyrJEWTXmKNCj87xgTpY5I7ARISeOQD8QIDAQABAoIBABYNN4l1dyRNiBBX
|
||||
XMJ6QzqYxgqRYqC3q02R8UOd7KKJDQps9sQg+KNMvsJSelfnMNo0Q63e08OiDldH
|
||||
F1d+oCzMeKW3U7irR1aBcXCGZvDtCs6frgrEVnqK1ga13/d+ZqCVnRngurIXJZyp
|
||||
UsW9NK1ONpwwDiwyIsimzvNd0oOoR6ROIN2Fk+AhKQ6bPdgqLM1Swx6BA0J/aaqO
|
||||
jAqSkYkGOEL970W8ZhnyyDDRcbgPbacUDo7AJnrBeqHoAqrJ1PzJ3jhcWDJl8Xcy
|
||||
uVDP1hBeK9yg4nuMcArsqrRQvqL2GuafGYygfzrU1aW96hlXciOv32ov36h2qIJU
|
||||
r4JfJGECgYEA7UPD4iRsHV6eMkD98Ev74ygdnFL2TMknqOUEboPNiQzSzr5oVrKa
|
||||
KFDhzenUNlMSoeiAaLLI7xaD4xptXuN8xx7sQZVSiEniBfJ7F+9sPNjCXwYbUuWp
|
||||
qpp6KfCrjLxDxgSKH9FUIlTvL7M4lmAD2yHn4zXjFz3BOs261JUn6l0CgYEA3K2/
|
||||
S2eP3VUL6K4+HNMzXTj9Q8S7LSYnTZVIjfek6pQHMwaMKE8EC7L4XeS9TZ49BKCS
|
||||
Mh9RI2yBCX6L1uo2zURAI0oDrowDhjaUCD4xxTD27OyMcvjdSzk/+0E+DtsWdgYm
|
||||
FGX/l0zTRUsZBbc7ItTG0ksIB+aMM4njBbHubqUCgYAq9llS6pt1Gfv1R5Vz3J5o
|
||||
vIvYEaGtt8Lpr0aFKHKgPWUysIG+KSsG39ZzbcLSb2pxTONrkewWdvI8vj1NsE2Y
|
||||
1L2dBofiS9aUkxq888qanflcMYPjF9kIHl6+l2jI3BI9mfbU2hes+8ovzfkSKaKp
|
||||
HFOb7dcID1Oc7UHGWpfWtQKBgQDC3Y4xOKbaLDJS6iIg9ALETAGgqQUbzjggkzU5
|
||||
X7e6CLL+xMZZBcUty4Dz8HuVIakCAAR4zByq6jJbvuofAj0YLy9vufjcVfj6uBEp
|
||||
4jmyxhUVi6BOGiHXPhuYc7koByCjYbSYiKUU5psc8j6LRIysqjVTFzxlNZkSHa1h
|
||||
pwhDnQKBgATpQou7MeAOMHjMPaNx8OCq7QNhocp8Q+goxPb0ND2jF9xSI+gjzRRt
|
||||
Kpz+xO6tri6wCgWrmE5cJbEe3/EYf3bmbNA9wOQ72kfoy9uO0cCi+5gSJigwaIKM
|
||||
DYRTDIS9eg2LF4B64hZvkCLTmP4rLJWdRnWrLosIC4rD1uWgGayC
|
||||
-----END RSA PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_privkey_enc():
|
||||
return """\
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIHU2H6hhL0gYCAggA
|
||||
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBD64PydhZIJPW9amw7M8yGvBIIE
|
||||
0LHXvvQleCJMlH/Rtml1Vx2nygReVl+1Ag+FjtsNQHtsXYkzVWSDI0zI7nFyDpb9
|
||||
Kr2+9UOsOhQA5/swka9ude4oJng0YZcV4qgar8yFncWTrMTk/mrvFSNZPz9LMGsq
|
||||
in7hzYGAP6XdprHgJfw+wDQfwbwcTQp5DUOPYbhxfnggVQBL84gp/2urCcNnFX+T
|
||||
OKGm9C3NfLycrCbaQxaV/2oTo7+UHUaXKwZwY6zKxCqbwGBy7dNcZD16nJyOBmbj
|
||||
ytOi/OqBcoj03yK4ETIm7EWwem6CRAbPH1GnUAxmb5tG6jzKphbMJur8n72Vv+VK
|
||||
9+Gkz5vOq1O1wlK+DfB+Xrgfx3lHHQllxi7FtlQegSFlIbHAacG/muwMRQ5PoMEp
|
||||
RaGQkxOhiU7VSaZ3Gdx3TrQMaF5nBqvs90Xw40uWdD9+Kd3Oqkj9OgiqHZwgWPfW
|
||||
txB+jXYGj1ERUvb36T7P8IH/QDa8jwVf3+f1pOpoMe4+6i3rr9bAkDhIjpNDo2a0
|
||||
YXvVns18UisnLXHxdAZb9R2V/VoTxhs3IqK3nEb5qnb1RAtJfV4p1ENVsoPiHl5C
|
||||
pq7xcRO+25hy18CjMWqj8t3PH5MdBL8UMFZyDnIH9z9N019U0ZIaD3NqiiRgGD+U
|
||||
CSLkoXq5oni5RkDQCnzJRFo/Vzmx2P5OJyZvHYLtVOUwsp1dW8JFtdKJoGBxNc1M
|
||||
kc7eevfwUZEDc2dHxcwxDj0Tas05DaMBib3Oi0D/ipxDdzW+uENQHdCwy7XZf+T+
|
||||
ig03Ega0/w+c/rdnUevdXK/L1sIO7F8hyDlVG1q0PeoJ8jXnZk+UfNYy820sPWIE
|
||||
IwtT1aODvnYgio8vgrDXpB0qVDNi2Ml83gYxznIQuxWg6dCrifvCa8TwCTe9tAhv
|
||||
gTkEkYdyBTpvT585z/1x+dra3uOGiMCN0rP3n3JaICDqCwImznvIP8kqNEnalWQj
|
||||
pUVI3nKZunTtrL9vAegW9jF0Ipvyf+VSQmw+yN5B35Qfy95CwAwtJ/HPjy1sZmJZ
|
||||
carKrlqoD4xdSyrIun3fraGTbM+u4S+USRjikce+pu1cHi70Y3xm4JBAZsRJgPwB
|
||||
G/Orf5yC+E2pCK+7rX3rWINgwmX/kk94EtnYbMeES+lhlKOu/mR09K00atuBEDnJ
|
||||
o0MCM0BWYy5XQ2RAJLKCdcuJ2aWs/+slKRzlTCWnCUgISng6KFpcyA0aS/8r3ZyH
|
||||
SKdoSSgOtAieE/TGll0wjvONMIMfoEgR40OBV8BCSF8zWASZBXASTTSlUcu2wQ0q
|
||||
/wPFS2KkBdBc+qr+TxDNoeFDX+Rh9Nai25O/xoRtCC7afHsd5aQ4yen5C34/jsR1
|
||||
2kuayvZJ2pgYfIobFdgq9qHi637dVeW8n09XRq6HWhZu1ODO5bGX2oLr64MJAmgi
|
||||
fA+zu5Dfoe2Q4N1Ja3y0M7Xpfws14jyFxnJ8dR/T6rIJOy1QtHGo3UTai8nSBqCP
|
||||
RJ766EKBW7j83/53aYyChHvTXEPf4C29iOur72iMAlT2S06K/SH4fFM3brBzz0Fq
|
||||
EykXIgConLXDwj9+87XKYmOQX/0UP2sxAno6gJakdzExIod+u5koXP1o9vL5zMlH
|
||||
ahZPgPpP2p2uAz1+9MHpVPo2EIrvibm5T89DznwuaEfe
|
||||
-----END ENCRYPTED PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def rsa_pubkey():
|
||||
return """\
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzIdEbSkbPIc5F/aewNoq
|
||||
WPsF/YP+DByMwvYs+0K+lehc39P82fL8K2GIaGMBBzqlsX6CplAzGcoEQEBLTouL
|
||||
m+JYC5e1zRjaml4M+Bid8A7qwdjlWd0enCAxVB9BMNnj/mokWzh3hAQMBXfmddGR
|
||||
hH0P9KXfjBNh2V09vfHdtS9XMEEQjN6vCxaezXqsOMN3bjRTIcUatH7dVUgUpt9c
|
||||
ye1mdbD5KVBgJ9MArc2tJ3rmB0lxjEbAhTEHrNnIkDOJCKE8TaQOW4RyVWlIvSEL
|
||||
+Ov0TPeXXaef8HJlkyIpKrCZ+c4i0N7qOlyrJEWTXmKNCj87xgTpY5I7ARISeOQD
|
||||
8QIDAQAB
|
||||
-----END PUBLIC KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def csr():
|
||||
return """\
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICRTCCAS0CAQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyH
|
||||
RG0pGzyHORf2nsDaKlj7Bf2D/gwcjML2LPtCvpXoXN/T/Nny/CthiGhjAQc6pbF+
|
||||
gqZQMxnKBEBAS06Li5viWAuXtc0Y2ppeDPgYnfAO6sHY5VndHpwgMVQfQTDZ4/5q
|
||||
JFs4d4QEDAV35nXRkYR9D/Sl34wTYdldPb3x3bUvVzBBEIzerwsWns16rDjDd240
|
||||
UyHFGrR+3VVIFKbfXMntZnWw+SlQYCfTAK3NrSd65gdJcYxGwIUxB6zZyJAziQih
|
||||
PE2kDluEclVpSL0hC/jr9Ez3l12nn/ByZZMiKSqwmfnOItDe6jpcqyRFk15ijQo/
|
||||
O8YE6WOSOwESEnjkA/ECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQB9PbGDorNt
|
||||
Tl4xYObUsQwUkMVRPI59MLLYKEJRu/DGSA4sKf/vLK1ypyLIvxNp4gNFgm28nDV2
|
||||
t2gQ+DpBvwC1+XZQDZjgL7pPtLvErGCs6O6Y5fW8Lywxx5GqiVTIic/XLKTijKJv
|
||||
EecvwPjWv1VgtBKLZxN18KgIIs2Sq/t+GYe+Lu30c92Lc5INbrwTIEDYNTHywKet
|
||||
8FTSaYEMU6sGgsrIC5VxNT00EgJHjyjdCVIqQr/LqKyBMqJICWUSPq2ufjwqFsFi
|
||||
q1HXd62bA8k27ukX7w8qWsk6fOTwPh5F3883L5jVqcRsL9pqb4RUugTh/aReVlKW
|
||||
0WMDRBksXs1E
|
||||
-----END CERTIFICATE REQUEST-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_cert():
|
||||
# the final newline here is important since it is compared
|
||||
# with the ca_server return, which is parsed to contain one
|
||||
return """\
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDODCCAiCgAwIBAgIIbfpgqP0VGPgwDQYJKoZIhvcNAQELBQAwKzELMAkGA1UE
|
||||
BhMCVVMxDTALBgNVBAMMBFRlc3QxDTALBgNVBAoMBFNhbHQwHhcNMjIxMTE1MTQw
|
||||
NDMzWhcNMzIxMTEyMTQwNDMzWjArMQswCQYDVQQGEwJVUzENMAsGA1UEAwwEVGVz
|
||||
dDENMAsGA1UECgwEU2FsdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AOGTScvrjcEt6vsJcG9RUp6fKaDNDWZnJET0omanK9ZwaoGpJPp8UDYe/8ADeI7N
|
||||
10wdyB4oDM9gRDjInBtdQO/PsrmKZF6LzqVFgLMxu2up+PHMi9z6B2P4esIAzMu9
|
||||
PYxc9zH4HzLImHqscVD2HCabsjp9X134Af7hVY5NN/W/4qTP7uOM20wSG2TPI6+B
|
||||
tA9VyPbEPMPRzXzrqc45rVYe6kb2bT84GE93Vcu/e5JZ/k2AKD8Hoa2cxLPsTLq5
|
||||
igl+D+k+dfUtiABiKPvVQiYBsD1fyHDn2m7B6pCgvrGqHjsoAKufgFnXy6PJRg7n
|
||||
vQfaxSiusM5s+VS+fjlvgwsCAwEAAaNgMF4wDwYDVR0TBAgwBgEB/wIBATALBgNV
|
||||
HQ8EBAMCAQYwHQYDVR0OBBYEFFzy8fRTKSOe7kBakqO0Ki71potnMB8GA1UdIwQY
|
||||
MBaAFFzy8fRTKSOe7kBakqO0Ki71potnMA0GCSqGSIb3DQEBCwUAA4IBAQBZS4MP
|
||||
fXYPoGZ66seM+0eikScZHirbRe8vHxHkujnTBUjQITKm86WeQgeBCD2pobgBGZtt
|
||||
5YFozM4cERqY7/1BdemUxFvPmMFFznt0TM5w+DfGWVK8un6SYwHnmBbnkWgX4Srm
|
||||
GsL0HHWxVXkGnFGFk6Sbo3vnN7CpkpQTWFqeQQ5rHOw91pt7KnNZwc6I3ZjrCUHJ
|
||||
+UmKKrga16a4Q+8FBpYdphQU609npo/0zuaE6FyiJYlW3tG+mlbbNgzY/+eUaxt2
|
||||
9Bp9mtA+Hkox551Mfpq45Oi+ehwMt0xjZCjuFCM78oiUdHCGO+EmcT7ogiYALiOF
|
||||
LN1w5sybsYwIw6QN
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_new_cert():
|
||||
return """\
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDNDCCAhygAwIBAgIUd9vWUmDYMY7l3hSOwMV4UO36zfMwDQYJKoZIhvcNAQEL
|
||||
BQAwKzELMAkGA1UEBhMCVVMxDTALBgNVBAMMBFRlc3QxDTALBgNVBAoMBFNhbHQw
|
||||
HhcNMjIxMTIxMTUyOTE1WhcNMjIxMjIxMTUyOTE1WjAbMRkwFwYDVQQDDBBTYWx0
|
||||
IG5ldyB0ZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzIdE
|
||||
bSkbPIc5F/aewNoqWPsF/YP+DByMwvYs+0K+lehc39P82fL8K2GIaGMBBzqlsX6C
|
||||
plAzGcoEQEBLTouLm+JYC5e1zRjaml4M+Bid8A7qwdjlWd0enCAxVB9BMNnj/mok
|
||||
Wzh3hAQMBXfmddGRhH0P9KXfjBNh2V09vfHdtS9XMEEQjN6vCxaezXqsOMN3bjRT
|
||||
IcUatH7dVUgUpt9cye1mdbD5KVBgJ9MArc2tJ3rmB0lxjEbAhTEHrNnIkDOJCKE8
|
||||
TaQOW4RyVWlIvSEL+Ov0TPeXXaef8HJlkyIpKrCZ+c4i0N7qOlyrJEWTXmKNCj87
|
||||
xgTpY5I7ARISeOQD8QIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE
|
||||
AwIBBjAdBgNVHQ4EFgQUkLZONoQf6p8T2tLmMuWJG3iSmeQwHwYDVR0jBBgwFoAU
|
||||
XPLx9FMpI57uQFqSo7QqLvWmi2cwDQYJKoZIhvcNAQELBQADggEBAI3P5XQAWV79
|
||||
7/8ARx8IW4zhn7MTwBSO7wlViQ9bNF0DFrMspajyUrtLVX1gg4UAhVon3dmHf/eq
|
||||
wt+oT6YjmDAhR3mWUl1kp/LvE6EQgAnpmoOWe3PjZOiyE11651zO9pMF68FHdsin
|
||||
TjKXsggEXTllc03VomuXDUvxz2nMh1TIUVdAFH+eDykp5EFqGmXvPEJ7eVUv6v/m
|
||||
rXM0cUNy6MAjQM49slAxU03yRBD+oBauaVewrg+HKmY9FuzYga46rcQciOxRbPyl
|
||||
FokHBycPfCXe7QyPLZe9Kqth5BWXdhyyqvKSErUV6glxiShVxX0ciDNziBfU9UCY
|
||||
TMwH/TREa3g=
|
||||
-----END CERTIFICATE-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_key():
|
||||
return """\
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4ZNJy+uNwS3q+wlwb1FSnp8poM0NZmckRPSiZqcr1nBqgakk
|
||||
+nxQNh7/wAN4js3XTB3IHigMz2BEOMicG11A78+yuYpkXovOpUWAszG7a6n48cyL
|
||||
3PoHY/h6wgDMy709jFz3MfgfMsiYeqxxUPYcJpuyOn1fXfgB/uFVjk039b/ipM/u
|
||||
44zbTBIbZM8jr4G0D1XI9sQ8w9HNfOupzjmtVh7qRvZtPzgYT3dVy797kln+TYAo
|
||||
PwehrZzEs+xMurmKCX4P6T519S2IAGIo+9VCJgGwPV/IcOfabsHqkKC+saoeOygA
|
||||
q5+AWdfLo8lGDue9B9rFKK6wzmz5VL5+OW+DCwIDAQABAoIBAFfImc9hu6iR1gAb
|
||||
jEXFwAE6r1iEc9KGEPdEvG52X/jzhn8u89UGy7BEIAL5VtE8Caz1agtSSqnpLKNs
|
||||
blO31q18hnDuCmFAxwpKIeuaTvV3EAoJL+Su6HFfIWaeKRSgcHNPOmOXy4xXw/75
|
||||
XJ/FJu9fZ9ybLaHEAgLObh0Sr9RSPQbZ72ZawPP8+5WCbR+2w90RApHXQL0piSbW
|
||||
lIx1NE6o5wQb3vik8z/k5FqLCY2a8++WNyfvS+WWFY5WXGI7ZiDDQk46gnslquH2
|
||||
Lon5CEn3JlTGQFhxaaa2ivssscf2lA2Rvm2E8o1rdZJS2OpSE0ai4TXY9XnyjZj1
|
||||
5usWIwECgYEA+3Mwu03A7PyLEBksS/u3MSo/176S9lF/uXcecQNdhAIalUZ8AgV3
|
||||
7HP2yI9ZC0ekA809ZzFjGFostXm9VfUOEZ549jLOMzvBtCdaI0aBUE8icu52fX4r
|
||||
fT2NY6hYgz5/fxD8sq1XH/fqNNexABwtViH6YAly/9A1/8M3BOWt72UCgYEA5ag8
|
||||
sIfiBUoWd1sS6qHDuugWlpx4ZWYC/59XEJyCN2wioP8qFji/aNZxF1wLfyQe/zaa
|
||||
YBFusjsBnSfBU1p4UKCRHWQ9/CnC0DzqTkyKC4Fv8GuxgywNm5W9gPKk7idHP7mw
|
||||
e+7Uvf1pOQccqEPh7yltpW+Xw27gfsC2DMAIGa8CgYByv/q5P56PiCCeVB6W/mR3
|
||||
l2RTPLEsn7y+EtJdmL+QgrVG8kedVImJ6tHwbRqhvyvmYD9pXGxwrJZCqy/wjkjB
|
||||
WaSyFjVrxBV99Yd5Ga/hyntaH+ELHA0UtoZTuHvMSTU9866ei+R6vlSvkM9B0ZoO
|
||||
+KqeMTG99HLwKVJudbKO0QKBgQCd33U49XBOqoufKSBr4yAmUH2Ws6GgMuxExUiY
|
||||
xr5NUyzK+B36gLA0ZZYAtOnCURZt4x9kgxdRtnZ5jma74ilrY7XeOpbRzfN6KyX3
|
||||
BW6wUh6da6rvvUztc5Z+Gk9+18mG6SOFTr04jgfTiCwPD/s06YnSfFAbrRDukZOU
|
||||
WD45SQKBgBvjSwl3AbPoJnRjZjGuCUMKQKrLm30xCeorxasu+di/4YV5Yd8VUjaO
|
||||
mYyqXW6bQndKLuXT+AXtCd/Xt2sI96z8mc0G5fImDUxQjMUuS3RyQK357cEOu8Zy
|
||||
HdI7Pfaf/l0HozAw/Al+LXbpmSBdfmz0U/EGAKRqXMW5+vQ7XHXD
|
||||
-----END RSA PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ca_key_enc():
|
||||
return """\
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIy/O+FhcKBKUCAggA
|
||||
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDtSfZzKh7brkHFw/s6bcbVBIIE
|
||||
0JcLyycDhdSPzL7Zm1+ZLavjxiuaGEaHU8hu8ZScqyjcdWbdOfOuqZgu7OzxwfIc
|
||||
8Q1bfqMGUfxPcs/JQh13CVOaDYmafeMZYN3rqsNoci11iaHDhTAqgYCM2iVXaFUt
|
||||
6ZdfW+/hEk+yHwK5K2R1/ks8buAe0OgjkV0N3DqAif93BPyFP6XT7btVMrorGJjh
|
||||
1OJjuw3q0xJ02rn7O5imaZ5NnCIDShkKwWO6sUew3QHhW61/nuCBPyJTsAO0L4+t
|
||||
9zjb2jOIIuvTpZUhAty6I+bKgaYLhsii7z5jVYpt+NbYpzIe+9RvAD1psGk9+bGD
|
||||
rN70Bnhx29mPEKdmozXVQ8GTqDOSQSYMr9aax+BhSJoTnCtVtGGX0LXE5Dvd/HHy
|
||||
+Yw2HFrVglptsPYo4EBKccC3FJlS0mL6yBW5NCpU7MOhDV/iOMbzM4bqwKG+jqaw
|
||||
sjIScCg+ljBxGhNrcMa0AEBWukTRe4gERpb8AyGKYOSVN6iZyP5qhN/Abu1asKrj
|
||||
c4NRUu3yILleZuxjkDd4w0CwhjlCaKFLsp1XeFE5ZHM5Iezi1/I4QMXFTydB1KnX
|
||||
xOSofZ7b7pnvOiBQG2nQzYSjSnBO7E7NQOhjvkRgcxNsdAQWADIqdE3bKZ8qcEZ6
|
||||
q1TE0XtcDgwFGwQF/cyuEEXyMAkQV687e8IdCjc+MbyyqUtQA9382JyjOuzavvMD
|
||||
nO5s80lB5aa0WHdE+Rg7KiBIwL1CjBSGSiggKvkG01ObeQL4DCQG6gHgz+nvdiNe
|
||||
du2u6hW2/PUuUIOM2ApE98T2TAzCnyu02iMIN5aH4za5y1w5YzaU4Lsl4nzAEA3c
|
||||
8EuVIWMutZnqT4ZSCLCq1AtDYkSXxIjGQPwhRslyCJuwtuiaDXLIZIpMRGqMKdGS
|
||||
c3q0k5ba92jXppIOVYN/kViNjYeHVZ3KRAi2MqUByqiMBkZo11NsgaU/uPsKsK16
|
||||
D0XueVs9EobU55tgBV71Q8g/5BiGG19W5UZVzjiiuGuj44msOfYV4027KqqFf302
|
||||
U5RXAwBko9S+v3SuTZrRXK4uuYceR9Uyco8aP/tNAhHEGa8Z73vLngZICp57qD1h
|
||||
8smjOrm1volZpu31HP9CWVh47GyuzSZ8BUFrR/uXfa+uqyLqeBKglz5SC6Ak3nL8
|
||||
eAHu3EK2dVp4vqwYB2oO9DQqs4CN7DKyArNeUzKSf6ZKEYBZCdF5V5HgbSpY5f+e
|
||||
xj5cpuMVc7s+Nxv/0bqxNzt8ghe2sDELxK8lo7Q6E+aUNBWt++nHI2b8y5ynaANU
|
||||
kQjeoorrPHUScXN8TVrgrIYIfXOqkI14UmroRH5/oyORHXN25JekV1DisKZOtSdV
|
||||
Vqt3o/hlGFYhaeznIgquBm27trLkLHOfCGx6M2xlKszlWBP03zFLp0PiXE+y07zC
|
||||
IwzaiVlj/O+QIsiMmrtc8WXYiNWVN5XDe1elFPs1K2cw0cIeyLgC1Bibxa7dH01G
|
||||
Z0Nr+hZN+/EqI3Tu+lWeWtj/lIhjJrKQvUOMM4W1MFZZdK09ZsCdW0Y1fFYn/3Xz
|
||||
g1KvGcFoszp0uMptlJUhsxtFooG4xKtgEITmtraRU+hTGU3NZgtk7Qff4tFa0O0h
|
||||
A62orBDc+8x+AehfwYSm11dz5/P6aL3QZf+tzr05vbVn
|
||||
-----END ENCRYPTED PRIVATE KEY-----"""
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cert_args(ca_minion_id, tmp_path, x509_data):
|
||||
return {
|
||||
"name": str(tmp_path / "cert_managed"),
|
||||
"ca_server": ca_minion_id,
|
||||
"signing_policy": "testpolicy",
|
||||
"private_key": str(x509_data / "key"),
|
||||
"CA": "from_args",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cert_args_exts():
|
||||
return {
|
||||
"basicConstraints": "critical, CA:TRUE, pathlen:1",
|
||||
"keyUsage": "critical, cRLSign, keyCertSign, digitalSignature",
|
||||
"extendedKeyUsage": "OCSPSigning",
|
||||
"subjectKeyIdentifier": "hash",
|
||||
"authorityKeyIdentifier": "keyid:always",
|
||||
"issuerAltName": "DNS:mysalt.ca",
|
||||
"authorityInfoAccess": "OCSP;URI:http://ocsp.salt.ca/",
|
||||
"subjectAltName": "DNS:me.salt.ca",
|
||||
"crlDistributionPoints": None,
|
||||
"certificatePolicies": "1.2.4.5",
|
||||
"policyConstraints": "requireExplicitPolicy:3",
|
||||
"inhibitAnyPolicy": 2,
|
||||
"nameConstraints": "permitted;IP:192.168.0.0/255.255.0.0,excluded;email:.com",
|
||||
"noCheck": True,
|
||||
"tlsfeature": "status_request",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(params=[{}])
|
||||
def existing_cert(x509_salt_call_cli, cert_args, ca_key, rsa_privkey, request):
|
||||
cert_args.update(request.param)
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
cert = _get_cert(cert_args["name"])
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
yield cert_args["name"]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_run_cli(x509_salt_master):
|
||||
return x509_salt_master.salt_run_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def x509_salt_call_cli(x509_salt_minion):
|
||||
return x509_salt_minion.salt_call_cli()
|
||||
|
||||
|
||||
def test_certificate_managed_remote(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey, x509_data
|
||||
):
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
cert = _get_cert(cert_args["name"])
|
||||
assert "CN=from_signing_policy" == cert.subject.rfc4514_string()
|
||||
assert _signed_by(cert, ca_key)
|
||||
assert _belongs_to(cert, rsa_privkey)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_cert")
|
||||
def test_certificate_managed_remote_no_changes(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"] == {}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_cert")
|
||||
def test_certificate_managed_remote_policy_change(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["signing_policy"] = "testchangepolicy"
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert "subject_name" in ret.data[next(iter(ret.data))]["changes"]
|
||||
cert = _get_cert(cert_args["name"])
|
||||
assert cert.subject.rfc4514_string() == "CN=from_changed_signing_policy"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_cert")
|
||||
def test_certificate_managed_remote_ca_cert_change(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["signing_policy"] = "testchangecapolicy"
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert ret.data
|
||||
changes = ret.data[next(iter(ret.data))]["changes"]
|
||||
assert changes
|
||||
assert "signing_private_key" in changes
|
||||
assert "issuer_name" in changes
|
||||
assert "extensions" in changes
|
||||
assert "authorityKeyIdentifier" in changes["extensions"]["changed"]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_cert")
|
||||
def test_certificate_managed_remote_no_changes_signing_policy_override(
|
||||
x509_salt_call_cli, cert_args, ca_key, rsa_privkey
|
||||
):
|
||||
cert_args["basicConstraints"] = "critical, CA:TRUE, pathlen:3"
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"] == {}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_cert")
|
||||
def test_certificate_managed_remote_renew(x509_salt_call_cli, cert_args):
|
||||
cert_cur = _get_cert(cert_args["name"])
|
||||
cert_args["days_remaining"] = 999
|
||||
ret = x509_salt_call_cli.run(
|
||||
"state.single", "x509.certificate_managed", **cert_args
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
cert_new = _get_cert(cert_args["name"])
|
||||
assert cert_cur.serial_number != cert_new.serial_number
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("privkey_new")
|
||||
def test_privkey_new_with_prereq(x509_salt_call_cli, tmp_path):
|
||||
cert_cur = _get_cert(tmp_path / "cert.pem")
|
||||
pk_cur = _get_privkey(tmp_path / "priv.key")
|
||||
assert _belongs_to(cert_cur, pk_cur)
|
||||
|
||||
ret = x509_salt_call_cli.run("state.apply", "manage_cert")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"]
|
||||
cert_new = _get_cert(tmp_path / "cert.pem")
|
||||
pk_new = _get_privkey(tmp_path / "priv.key")
|
||||
assert _belongs_to(cert_new, pk_new)
|
||||
assert not _belongs_to(cert_new, pk_cur)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("privkey_new_pkcs12")
|
||||
@pytest.mark.skipif(
|
||||
CRYPTOGRAPHY_VERSION[0] < 36,
|
||||
reason="Complete PKCS12 deserialization requires cryptography v36+",
|
||||
)
|
||||
def test_privkey_new_with_prereq_pkcs12(x509_salt_call_cli, tmp_path):
|
||||
cert_cur = _get_cert(tmp_path / "cert", encoding="pkcs12").cert.certificate
|
||||
pk_cur = _get_privkey(tmp_path / "cert", encoding="pkcs12")
|
||||
assert _belongs_to(cert_cur, pk_cur)
|
||||
|
||||
ret = x509_salt_call_cli.run("state.apply", "manage_cert")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data[next(iter(ret.data))]["changes"]
|
||||
cert_new = _get_cert(tmp_path / "cert", encoding="pkcs12").cert.certificate
|
||||
pk_new = _get_privkey(tmp_path / "cert", encoding="pkcs12")
|
||||
assert _belongs_to(cert_new, pk_new)
|
||||
assert not _belongs_to(cert_new, pk_cur)
|
||||
|
||||
|
||||
def _belongs_to(cert_or_pubkey, privkey):
|
||||
if isinstance(cert_or_pubkey, cx509.Certificate):
|
||||
cert_or_pubkey = cert_or_pubkey.public_key()
|
||||
return x509util.is_pair(cert_or_pubkey, x509util.load_privkey(privkey))
|
||||
|
||||
|
||||
def _signed_by(cert, privkey):
|
||||
return x509util.verify_signature(cert, x509util.load_privkey(privkey).public_key())
|
||||
|
||||
|
||||
def _get_cert(cert, encoding="pem", passphrase=None):
|
||||
try:
|
||||
p = Path(cert)
|
||||
if p.exists():
|
||||
cert = p.read_bytes()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
|
||||
if "pem" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = cert.encode()
|
||||
return cx509.load_pem_x509_certificate(cert)
|
||||
if "der" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
return cx509.load_der_x509_certificate(cert)
|
||||
if "pkcs7_pem" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = cert.encode()
|
||||
return pkcs7.load_pem_pkcs7_certificates(cert)
|
||||
if "pkcs7_der" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
return pkcs7.load_der_pkcs7_certificates(cert)
|
||||
if "pkcs12" == encoding:
|
||||
if not isinstance(cert, bytes):
|
||||
cert = base64.b64decode(cert)
|
||||
if passphrase is not None and not isinstance(passphrase, bytes):
|
||||
passphrase = passphrase.encode()
|
||||
return pkcs12.load_pkcs12(cert, passphrase)
|
||||
|
||||
|
||||
def _get_privkey(pk, encoding="pem", passphrase=None):
|
||||
try:
|
||||
p = Path(pk)
|
||||
if p.exists():
|
||||
pk = p.read_bytes()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
if passphrase is not None:
|
||||
passphrase = passphrase.encode()
|
||||
|
||||
if "pem" == encoding:
|
||||
if not isinstance(pk, bytes):
|
||||
pk = pk.encode()
|
||||
return load_pem_private_key(pk, passphrase)
|
||||
if "der" == encoding:
|
||||
if not isinstance(pk, bytes):
|
||||
pk = base64.b64decode(pk)
|
||||
return load_der_private_key(pk, passphrase)
|
||||
if "pkcs12" == encoding:
|
||||
if not isinstance(pk, bytes):
|
||||
pk = base64.b64decode(pk)
|
||||
return pkcs12.load_pkcs12(pk, passphrase).key
|
||||
raise ValueError("Need correct encoding")
|
1716
tests/pytests/unit/utils/test_x509.py
Normal file
1716
tests/pytests/unit/utils/test_x509.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue