1
0
mirror of https://github.com/github/octodns.git synced 2024-05-11 05:55:00 +00:00
Files
github-octodns/octodns/record/tlsa.py
2023-01-02 14:33:44 -05:00

161 lines
4.9 KiB
Python

#
#
#
from ..equality import EqualityTupleMixin
from .base import Record, ValuesMixin
from .rr import RrParseError
class TlsaValue(EqualityTupleMixin, dict):
@classmethod
def parse_rdata_text(self, value):
try:
(
certificate_usage,
selector,
matching_type,
certificate_association_data,
) = value.split(' ')
except ValueError:
raise RrParseError()
try:
certificate_usage = int(certificate_usage)
except ValueError:
pass
try:
selector = int(selector)
except ValueError:
pass
try:
matching_type = int(matching_type)
except ValueError:
pass
return {
'certificate_usage': certificate_usage,
'selector': selector,
'matching_type': matching_type,
'certificate_association_data': certificate_association_data,
}
@classmethod
def validate(cls, data, _type):
if not isinstance(data, (list, tuple)):
data = (data,)
reasons = []
for value in data:
try:
certificate_usage = int(value.get('certificate_usage', 0))
if certificate_usage < 0 or certificate_usage > 3:
reasons.append(
f'invalid certificate_usage ' f'"{certificate_usage}"'
)
except ValueError:
reasons.append(
f'invalid certificate_usage '
f'"{value["certificate_usage"]}"'
)
try:
selector = int(value.get('selector', 0))
if selector < 0 or selector > 1:
reasons.append(f'invalid selector "{selector}"')
except ValueError:
reasons.append(f'invalid selector "{value["selector"]}"')
try:
matching_type = int(value.get('matching_type', 0))
if matching_type < 0 or matching_type > 2:
reasons.append(f'invalid matching_type "{matching_type}"')
except ValueError:
reasons.append(
f'invalid matching_type ' f'"{value["matching_type"]}"'
)
if 'certificate_usage' not in value:
reasons.append('missing certificate_usage')
if 'selector' not in value:
reasons.append('missing selector')
if 'matching_type' not in value:
reasons.append('missing matching_type')
if 'certificate_association_data' not in value:
reasons.append('missing certificate_association_data')
return reasons
@classmethod
def process(cls, values):
return [cls(v) for v in values]
def __init__(self, value):
super().__init__(
{
'certificate_usage': int(value.get('certificate_usage', 0)),
'selector': int(value.get('selector', 0)),
'matching_type': int(value.get('matching_type', 0)),
# force it to a string, in case the hex has only numerical
# values and it was converted to an int at some point
# TODO: this needed on any others?
'certificate_association_data': str(
value['certificate_association_data']
),
}
)
@property
def certificate_usage(self):
return self['certificate_usage']
@certificate_usage.setter
def certificate_usage(self, value):
self['certificate_usage'] = value
@property
def selector(self):
return self['selector']
@selector.setter
def selector(self, value):
self['selector'] = value
@property
def matching_type(self):
return self['matching_type']
@matching_type.setter
def matching_type(self, value):
self['matching_type'] = value
@property
def certificate_association_data(self):
return self['certificate_association_data']
@certificate_association_data.setter
def certificate_association_data(self, value):
self['certificate_association_data'] = value
@property
def rdata_text(self):
return f'{self.certificate_usage} {self.selector} {self.matching_type} {self.certificate_association_data}'
def _equality_tuple(self):
return (
self.certificate_usage,
self.selector,
self.matching_type,
self.certificate_association_data,
)
def __repr__(self):
return (
f"'{self.certificate_usage} {self.selector} '"
f"'{self.matching_type} {self.certificate_association_data}'"
)
class TlsaRecord(ValuesMixin, Record):
_type = 'TLSA'
_value_type = TlsaValue
Record.register_type(TlsaRecord)