2023-03-22 14:22:54 +01:00
'''
todo : allow_self_signed
todo : allow_bad_domain
2023-03-22 15:19:36 +01:00
todo :
2023-03-22 14:22:54 +01:00
'''
class implementation_check_kind_tls_certificate ( interface_check_kind ) :
'''
[ implementation ]
'''
def parameters_schema ( self ) :
return {
" type " : " object " ,
" additionalProperties " : False ,
" properties " : {
" host " : {
" type " : " string "
} ,
2023-03-22 15:19:36 +01:00
" port " : {
" type " : " integer " ,
" default " : 443
} ,
2023-06-18 21:11:37 +02:00
" expiry_threshold_concerning " : {
" description " : " in days; allowed amount of valid days before the certificate expires; threshold for condition ' concerning ' ; ' null ' means ' report at no value ' " ,
2023-03-22 14:22:54 +01:00
" type " : [ " null " , " integer " ] ,
" default " : 7 ,
" minimum " : 0
2023-06-18 21:11:37 +02:00
} ,
" expiry_threshold_critical " : {
" description " : " in days; allowed amount of valid days before the certificate expires; threshold for condition ' critical ' ; ' null ' means ' report at no value ' " ,
" type " : [ " null " , " integer " ] ,
" default " : 1 ,
" minimum " : 0
} ,
" expiry_threshold " : {
" deprecated " : True ,
" description " : " " ,
" type " : [ " null " , " integer " ] ,
" minimum " : 0 ,
" default " : None ,
} ,
" strict " : {
" deprecated " : True ,
" description " : " " ,
" type " : [ " null " , " boolean " ] ,
" default " : None ,
} ,
2023-03-22 14:22:54 +01:00
} ,
" required " : [
2023-06-18 21:11:37 +02:00
" host " ,
2023-03-22 14:22:54 +01:00
]
}
'''
[ implementation ]
'''
2023-04-28 17:30:51 +02:00
def normalize_order_node ( self , node ) :
2023-06-18 21:11:37 +02:00
version = (
" v1 "
if (
( not ( " expiry_threshold_concerning " in node ) )
and
( not ( " expiry_threshold_critical " in node ) )
) else
" v2 "
)
if ( version == " v1 " ) :
if ( not " host " in node ) :
raise ValueError ( " missing mandatory field ' host ' " )
else :
node_ = dict_merge (
{
" port " : 443 ,
" expiry_threshold " : 7 ,
" strict " : True ,
# "allow_self_signed": False,
# "allow_bad_domain": False,
} ,
node
)
return {
" port " : node_ [ " port " ] ,
" expiry_threshold_concerning " : (
None
if node_ [ " strict " ] else
node_ [ " expiry_threshold " ]
) ,
" expiry_threshold_critical " : (
node_ [ " expiry_threshold " ]
if node_ [ " strict " ] else
None
) ,
}
elif ( version == " v2 " ) :
if ( not " host " in node ) :
raise ValueError ( " missing mandatory field ' host ' " )
else :
node_ = dict_merge (
{
" port " : 443 ,
" expiry_threshold_concerning " : 7 ,
" expiry_threshold_critical " : 1 ,
# "allow_self_signed": False,
# "allow_bad_domain": False,
} ,
node
)
return node_
2023-03-22 14:22:54 +01:00
else :
2023-06-18 21:11:37 +02:00
raise ValueError ( " unhandled " )
2023-03-22 14:22:54 +01:00
'''
[ implementation ]
'''
def run ( self , parameters ) :
2023-04-28 17:30:51 +02:00
faults = [ ]
data = { }
2023-03-22 14:22:54 +01:00
context = _ssl . create_default_context ( )
2023-06-18 21:11:37 +02:00
condition = enum_condition . ok
2023-03-22 14:22:54 +01:00
try :
2023-03-22 15:19:36 +01:00
socket = _socket . create_connection ( ( parameters [ " host " ] , parameters [ " port " ] , ) )
2023-03-22 14:22:54 +01:00
socket_wrapped = context . wrap_socket ( socket , server_hostname = parameters [ " host " ] )
version = socket_wrapped . version ( )
2023-04-28 17:30:51 +02:00
stuff = socket_wrapped . getpeercert ( False )
2023-03-22 14:22:54 +01:00
except _ssl . SSLCertVerificationError as error :
version = None
2023-04-28 17:30:51 +02:00
stuff = None
if ( stuff is None ) :
faults . append ( translation_get ( " checks.tls_certificate.not_obtainable " ) )
2023-06-18 21:11:37 +02:00
condition = enum_condition . critical
2023-03-22 14:22:54 +01:00
else :
# version == "TLSv1.3"
2023-04-28 17:30:51 +02:00
expiry_timestamp = _ssl . cert_time_to_seconds ( stuff [ " notAfter " ] )
2023-03-22 14:22:54 +01:00
current_timestamp = get_current_timestamp ( )
days = _math . ceil ( ( expiry_timestamp - current_timestamp ) / ( 60 * 60 * 24 ) )
2023-04-28 17:30:51 +02:00
data = dict_merge (
data ,
{
" expiry_timestamp " : expiry_timestamp ,
" days " : days ,
} ,
)
2023-06-18 21:11:37 +02:00
if (
( parameters [ " expiry_threshold_critical " ] is not None )
and
( days < = parameters [ " expiry_threshold_critical " ] )
) :
2023-04-28 17:30:51 +02:00
faults . append ( translation_get ( " checks.tls_certificate.expires_soon " ) )
2023-06-18 21:11:37 +02:00
condition = enum_condition . critical
2023-03-22 14:22:54 +01:00
else :
2023-06-18 21:11:37 +02:00
if (
( parameters [ " expiry_threshold_concerning " ] is not None )
and
( days < = parameters [ " expiry_threshold_concerning " ] )
) :
faults . append ( translation_get ( " checks.tls_certificate.expires_soon " ) )
condition = enum_condition . concerning
else :
pass
2023-04-28 17:30:51 +02:00
return {
2023-06-18 21:11:37 +02:00
" condition " : condition ,
2023-04-28 17:30:51 +02:00
" info " : {
" host " : parameters [ " host " ] ,
" port " : parameters [ " port " ] ,
" faults " : faults ,
" data " : data ,
}
}