mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Helpful log messages for when things go wrong
Provide helpful log messages on the master and minions if a minion uses signing or encryption that is not suppoted by the master.
This commit is contained in:
parent
80a2f65e58
commit
534bf76463
4 changed files with 89 additions and 32 deletions
|
@ -22,7 +22,7 @@ import salt.utils.minions
|
|||
import salt.utils.platform
|
||||
import salt.utils.stringutils
|
||||
import salt.utils.verify
|
||||
from salt.exceptions import SaltDeserializationError
|
||||
from salt.exceptions import SaltDeserializationError, UnsupportedAlgorithm
|
||||
from salt.utils.cache import CacheCli
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -237,15 +237,22 @@ class ReqServerChannel:
|
|||
return pret
|
||||
|
||||
def _clear_signed(self, load, algorithm):
|
||||
master_pem_path = os.path.join(self.opts["pki_dir"], "master.pem")
|
||||
tosign = salt.payload.dumps(load)
|
||||
return {
|
||||
"enc": "clear",
|
||||
"load": tosign,
|
||||
"sig": salt.crypt.PrivateKey(master_pem_path).sign(
|
||||
tosign, algorithm=algorithm
|
||||
),
|
||||
}
|
||||
try:
|
||||
master_pem_path = os.path.join(self.opts["pki_dir"], "master.pem")
|
||||
tosign = salt.payload.dumps(load)
|
||||
return {
|
||||
"enc": "clear",
|
||||
"load": tosign,
|
||||
"sig": salt.crypt.PrivateKey(master_pem_path).sign(
|
||||
tosign, algorithm=algorithm
|
||||
),
|
||||
}
|
||||
except UnsupportedAlgorithm:
|
||||
log.info(
|
||||
"Minion tried to authenticate with unsupported signing algorithm: %s",
|
||||
algorithm,
|
||||
)
|
||||
return {"enc": "clear", "load": {"ret": "bad sig algo"}}
|
||||
|
||||
def _update_aes(self):
|
||||
"""
|
||||
|
@ -678,6 +685,13 @@ class ReqServerChannel:
|
|||
aes = "{}_|-{}".format(
|
||||
salt.master.SMaster.secrets["aes"]["secret"].value, mtoken
|
||||
)
|
||||
except UnsupportedAlgorithm as exc:
|
||||
log.info(
|
||||
"Minion %s tried to authenticate with unsupported encryption algorithm: %s",
|
||||
load["id"],
|
||||
enc_algo,
|
||||
)
|
||||
return {"enc": "clear", "load": {"ret": "bad enc algo"}}
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.warning("Token failed to decrypt %s", exc)
|
||||
# Token failed to decrypt, send back the salty bacon to
|
||||
|
@ -691,10 +705,17 @@ class ReqServerChannel:
|
|||
try:
|
||||
mtoken = self.master_key.key.decrypt(load["token"], enc_algo)
|
||||
ret["token"] = pub.encrypt(mtoken, enc_algo)
|
||||
except UnsupportedAlgorithm as exc:
|
||||
log.info(
|
||||
"Minion %s tried to authenticate with unsupported encryption algorithm: %s",
|
||||
load["id"],
|
||||
enc_algo,
|
||||
)
|
||||
return {"enc": "clear", "load": {"ret": "bad enc algo"}}
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
# Token failed to decrypt, send back the salty bacon to
|
||||
# support older minions
|
||||
log.warning("Token failed to decrypt: %s", exc)
|
||||
log.warning("Token failed to decrypt: %r", exc)
|
||||
|
||||
aes = salt.master.SMaster.secrets["aes"]["secret"].value
|
||||
ret["aes"] = pub.encrypt(aes, enc_algo)
|
||||
|
|
|
@ -40,6 +40,7 @@ from salt.exceptions import (
|
|||
MasterExit,
|
||||
SaltClientError,
|
||||
SaltReqTimeoutError,
|
||||
UnsupportedAlgorithm,
|
||||
)
|
||||
|
||||
try:
|
||||
|
@ -238,19 +239,27 @@ class PrivateKey(BaseKey):
|
|||
def sign(self, data, algorithm=PKCS1v15_SHA1):
|
||||
_padding = self.parse_padding_for_signing(algorithm)
|
||||
_hash = self.parse_hash(algorithm)
|
||||
return self.key.sign(salt.utils.stringutils.to_bytes(data), _padding(), _hash())
|
||||
try:
|
||||
return self.key.sign(
|
||||
salt.utils.stringutils.to_bytes(data), _padding(), _hash()
|
||||
)
|
||||
except cryptography.exceptions.UnsupportedAlgorithm:
|
||||
raise UnsupportedAlgorithm(f"Unsupported algorithm: {algorithm}")
|
||||
|
||||
def decrypt(self, data, algorithm=OAEP_SHA1):
|
||||
_padding = self.parse_padding_for_encryption(algorithm)
|
||||
_hash = self.parse_hash(algorithm)
|
||||
return self.key.decrypt(
|
||||
data,
|
||||
_padding(
|
||||
mgf=padding.MGF1(algorithm=_hash()),
|
||||
algorithm=_hash(),
|
||||
label=None,
|
||||
),
|
||||
)
|
||||
try:
|
||||
return self.key.decrypt(
|
||||
data,
|
||||
_padding(
|
||||
mgf=padding.MGF1(algorithm=_hash()),
|
||||
algorithm=_hash(),
|
||||
label=None,
|
||||
),
|
||||
)
|
||||
except cryptography.exceptions.UnsupportedAlgorithm:
|
||||
raise UnsupportedAlgorithm(f"Unsupported algorithm: {algorithm}")
|
||||
|
||||
|
||||
class PublicKey(BaseKey):
|
||||
|
@ -265,14 +274,17 @@ class PublicKey(BaseKey):
|
|||
_padding = self.parse_padding_for_encryption(algorithm)
|
||||
_hash = self.parse_hash(algorithm)
|
||||
bdata = salt.utils.stringutils.to_bytes(data)
|
||||
return self.key.encrypt(
|
||||
bdata,
|
||||
_padding(
|
||||
mgf=padding.MGF1(algorithm=_hash()),
|
||||
algorithm=_hash(),
|
||||
label=None,
|
||||
),
|
||||
)
|
||||
try:
|
||||
return self.key.encrypt(
|
||||
bdata,
|
||||
_padding(
|
||||
mgf=padding.MGF1(algorithm=_hash()),
|
||||
algorithm=_hash(),
|
||||
label=None,
|
||||
),
|
||||
)
|
||||
except cryptography.exceptions.UnsupportedAlgorithm:
|
||||
raise UnsupportedAlgorithm(f"Unsupported algorithm: {algorithm}")
|
||||
|
||||
def verify(self, data, signature, algorithm=PKCS1v15_SHA1):
|
||||
_padding = self.parse_padding_for_signing(algorithm)
|
||||
|
@ -752,6 +764,18 @@ class AsyncAuth:
|
|||
"Authentication wait time is %s", acceptance_wait_time
|
||||
)
|
||||
continue
|
||||
elif creds == "bad enc algo":
|
||||
log.error(
|
||||
"This minion is using a encryption algorithm that is "
|
||||
"not supported by it's Master. Please check your minion configutation."
|
||||
)
|
||||
break
|
||||
elif creds == "bad sig algo":
|
||||
log.error(
|
||||
"This minion is using a signing algorithm that is "
|
||||
"not supported by it's Master. Please check your minion configutation."
|
||||
)
|
||||
break
|
||||
break
|
||||
if not isinstance(creds, dict) or "aes" not in creds:
|
||||
if self.opts.get("detect_mode") is True:
|
||||
|
@ -853,6 +877,13 @@ class AsyncAuth:
|
|||
if not isinstance(payload, dict) or "load" not in payload:
|
||||
log.error("Sign-in attempt failed: %s", payload)
|
||||
return False
|
||||
elif isinstance(payload["load"], dict) and "ret" in payload["load"]:
|
||||
if payload["load"]["ret"] == "bad enc algo":
|
||||
log.error("Sign-in attempt failed: %s", payload)
|
||||
return "bad enc algo"
|
||||
elif payload["load"]["ret"] == "bad sig algo":
|
||||
log.error("Sign-in attempt failed: %s", payload)
|
||||
return "bad sig algo"
|
||||
|
||||
clear_signed_data = payload["load"]
|
||||
clear_signature = payload["sig"]
|
||||
|
|
|
@ -362,6 +362,12 @@ class AuthorizationError(SaltException):
|
|||
"""
|
||||
|
||||
|
||||
class UnsupportedAlgorithm(SaltException):
|
||||
"""
|
||||
Thrown when a requested encryption or signing algorithm is un-supported.
|
||||
"""
|
||||
|
||||
|
||||
class SaltDaemonNotRunning(SaltException):
|
||||
"""
|
||||
Throw when a running master/minion/syndic is not running but is needed to
|
||||
|
|
|
@ -2,7 +2,6 @@ import hashlib
|
|||
import hmac
|
||||
import os
|
||||
|
||||
import cryptography.exceptions
|
||||
import pytest
|
||||
from cryptography.hazmat.backends.openssl import backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
|
@ -344,7 +343,7 @@ def test_loading_encrypted_openssl_format(openssl_encrypted_key, passphrase, tmp
|
|||
@pytest.mark.skipif(not FIPS_TESTRUN, reason="Only valid when in FIPS mode")
|
||||
def test_fips_bad_signing_algo(private_key, passphrase):
|
||||
key = salt.crypt.PrivateKey(private_key, passphrase)
|
||||
with pytest.raises(cryptography.exceptions.UnsupportedAlgorithm):
|
||||
with pytest.raises(salt.exceptions.UnsupportedAlgorithm):
|
||||
key.sign("meh", salt.crypt.PKCS1v15_SHA1)
|
||||
|
||||
|
||||
|
@ -361,7 +360,7 @@ def test_fips_bad_signing_algo_verification(private_key, passphrase):
|
|||
@pytest.mark.skipif(not FIPS_TESTRUN, reason="Only valid when in FIPS mode")
|
||||
def test_fips_bad_encryption_algo(private_key, passphrase):
|
||||
key = salt.crypt.PublicKey(private_key.replace(".pem", ".pub"))
|
||||
with pytest.raises(cryptography.exceptions.UnsupportedAlgorithm):
|
||||
with pytest.raises(salt.exceptions.UnsupportedAlgorithm):
|
||||
key.encrypt("meh", salt.crypt.OAEP_SHA1)
|
||||
|
||||
|
||||
|
@ -370,5 +369,5 @@ def test_fips_bad_decryption_algo(private_key, passphrase):
|
|||
pubkey = LegacyPublicKey(private_key.replace(".pem", ".pub"))
|
||||
data = pubkey.encrypt("meh")
|
||||
key = salt.crypt.PrivateKey(private_key, passphrase)
|
||||
with pytest.raises(cryptography.exceptions.UnsupportedAlgorithm):
|
||||
with pytest.raises(salt.exceptions.UnsupportedAlgorithm):
|
||||
key.decrypt(data)
|
||||
|
|
Loading…
Add table
Reference in a new issue