Common: Allow identities or secrets to be None
It's possible that credentials are stolen and an identity/secret association can not be made. For example, a list of usernames can be acquired by `ls /home`, but no passwords will be retrieved this way. Credentials(identity=Username("username"), secret=None) will represent this case.
This commit is contained in:
parent
e3b23993fa
commit
2af713dabd
|
@ -1,7 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Mapping, MutableMapping, Sequence, Type
|
||||
from typing import Any, Mapping, MutableMapping, Optional, Sequence, Type
|
||||
|
||||
from marshmallow import Schema, fields, post_load, pre_dump
|
||||
from marshmallow.exceptions import MarshmallowError
|
||||
|
@ -42,8 +42,8 @@ CREDENTIAL_COMPONENT_TYPE_TO_CLASS_SCHEMA: Mapping[CredentialComponentType, Sche
|
|||
|
||||
|
||||
class CredentialsSchema(Schema):
|
||||
identity = fields.Mapping()
|
||||
secret = fields.Mapping()
|
||||
identity = fields.Mapping(allow_none=True)
|
||||
secret = fields.Mapping(allow_none=True)
|
||||
|
||||
@post_load
|
||||
def _make_credentials(
|
||||
|
@ -55,9 +55,16 @@ class CredentialsSchema(Schema):
|
|||
return data
|
||||
|
||||
@staticmethod
|
||||
def _build_credential_component(data: Mapping[str, Any]) -> ICredentialComponent:
|
||||
def _build_credential_component(
|
||||
credential_component: Optional[Mapping[str, Any]]
|
||||
) -> Optional[ICredentialComponent]:
|
||||
if credential_component is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
credential_component_type = CredentialComponentType[data["credential_type"]]
|
||||
credential_component_type = CredentialComponentType[
|
||||
credential_component["credential_type"]
|
||||
]
|
||||
except KeyError as err:
|
||||
raise InvalidCredentialsError(f"Unknown credential component type {err}")
|
||||
|
||||
|
@ -67,7 +74,9 @@ class CredentialsSchema(Schema):
|
|||
]
|
||||
|
||||
try:
|
||||
return credential_component_class(**credential_component_schema.load(data))
|
||||
return credential_component_class(
|
||||
**credential_component_schema.load(credential_component)
|
||||
)
|
||||
except MarshmallowError as err:
|
||||
raise InvalidCredentialComponentError(credential_component_class, str(err))
|
||||
|
||||
|
@ -84,8 +93,11 @@ class CredentialsSchema(Schema):
|
|||
|
||||
@staticmethod
|
||||
def _serialize_credential_component(
|
||||
credential_component: ICredentialComponent,
|
||||
) -> Mapping[str, Any]:
|
||||
credential_component: Optional[ICredentialComponent],
|
||||
) -> Optional[Mapping[str, Any]]:
|
||||
if credential_component is None:
|
||||
return None
|
||||
|
||||
credential_component_schema = CREDENTIAL_COMPONENT_TYPE_TO_CLASS_SCHEMA[
|
||||
credential_component.credential_type
|
||||
]
|
||||
|
@ -95,8 +107,8 @@ class CredentialsSchema(Schema):
|
|||
|
||||
@dataclass(frozen=True)
|
||||
class Credentials(IJSONSerializable):
|
||||
identity: ICredentialComponent
|
||||
secret: ICredentialComponent
|
||||
identity: Optional[ICredentialComponent]
|
||||
secret: Optional[ICredentialComponent]
|
||||
|
||||
@staticmethod
|
||||
def from_mapping(credentials: Mapping) -> Credentials:
|
||||
|
|
|
@ -22,14 +22,15 @@ from common.credentials import (
|
|||
Username,
|
||||
)
|
||||
|
||||
IDENTITIES = [Username(USERNAME)]
|
||||
IDENTITY_DICTS = [{"credential_type": "USERNAME", "username": USERNAME}]
|
||||
IDENTITIES = [Username(USERNAME), None]
|
||||
IDENTITY_DICTS = [{"credential_type": "USERNAME", "username": USERNAME}, None]
|
||||
|
||||
SECRETS = (
|
||||
Password(PASSWORD_1),
|
||||
LMHash(LM_HASH),
|
||||
NTHash(NT_HASH),
|
||||
SSHKeypair(PRIVATE_KEY, PUBLIC_KEY),
|
||||
None,
|
||||
)
|
||||
SECRET_DICTS = [
|
||||
{"credential_type": "PASSWORD", "password": PASSWORD_1},
|
||||
|
@ -40,13 +41,19 @@ SECRET_DICTS = [
|
|||
"public_key": PUBLIC_KEY,
|
||||
"private_key": PRIVATE_KEY,
|
||||
},
|
||||
None,
|
||||
]
|
||||
|
||||
CREDENTIALS = [Credentials(identity, secret) for identity, secret in product(IDENTITIES, SECRETS)]
|
||||
CREDENTIALS = [
|
||||
Credentials(identity, secret)
|
||||
for identity, secret in product(IDENTITIES, SECRETS)
|
||||
if not (identity is None and secret is None)
|
||||
]
|
||||
|
||||
CREDENTIALS_DICTS = [
|
||||
{"identity": identity, "secret": secret}
|
||||
for identity, secret in product(IDENTITY_DICTS, SECRET_DICTS)
|
||||
if not (identity is None and secret is None)
|
||||
]
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue