Skip to content

Commit f2597c3

Browse files
authored
Support availability checking for url with path
1 parent ab38a2f commit f2597c3

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Please use `build_in_docker = true` and build inside docker for avoid nassl prob
3333
| certificate_expiration_notice_days | Days prior to the notification of the expired certificate. | `string` | `"7"` | no |
3434
| cloudwatch_logs_retention_in_days | Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `14` | no |
3535
| function_name | Lambda function name. | `string` | `"ssl-checker"` | no |
36-
| hostnames | The list of DNS names that should be monitored. e.g.: [\"example.com\"]. | `list(string)` | | yes |
36+
| hostnames | The list of DNS names that should be monitored. Path is also supported. e.g.: [\"example.com\",\"example.com/api\"]. | `list(string)` | | yes |
3737
| health_check_matcher | The response HTTP codes to use when checking for a healthy responses from a hostnames. e.g.: \"200,201,202-399\". | `string` | `"200-399"` | no |
3838
| scan_commands | List of scan commands types witch will run against hostnames. Any type supported by [SSLyze](https://nabla-c0d3.github.io/sslyze/documentation/available-scan-commands.html). | `list(string)` | `["certificate_info", "robot", "tls_compression", "tls_fallback_scsv", "heartbleed","http_headers", "openssl_ccs_injection", "session_renegotiation", "tls_1_1_cipher_suites","tls_1_2_cipher_suites", "tls_1_3_cipher_suites"]` | no |
3939
| schedule_expression | The scheduling expression. How often check hostnames. For example, `cron(0/5 * * * ? *)` or `rate(5 minutes)`. | `string` | `"cron(0/5 * * * ? *)"` | no |
@@ -65,3 +65,14 @@ Configuration is done via env variables
6565
# Example message
6666

6767
![Example](doc/example.jpg)
68+
69+
# Development
70+
71+
```
72+
bash setup.sh
73+
source env/bin/activate
74+
export SCAN_COMMANDS="certificate_info,robot,tls_compression,tls_fallback_scsv,heartbleed,http_headers,openssl_ccs_injection,session_renegotiation,tls_1_1_cipher_suites,tls_1_2_cipher_suites,tls_1_3_cipher_suites"
75+
export CERTIFICATE_EXPIRATION_NOTICE_DAYS=7
76+
export HEALTH_CHECK_MATCHER=200-399
77+
HOOK_URL="opa" DEBUG=true HOSTNAMES="google.com,g00gle.com" python3 ssl-check-to-slack.py
78+
```

ssl-check-to-slack.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sslyze import ServerScanRequest
1212
from sslyze import ScanCommand
1313
from datetime import datetime
14+
from urllib.parse import urlparse
1415

1516
logger = logging.getLogger()
1617
logger.setLevel(logging.INFO)
@@ -26,9 +27,9 @@ def read_env_variable_or_die(env_var_name):
2627
return value
2728

2829

29-
def get_response_status(hostname):
30+
def get_response_status(hostname,endpoint):
3031
connection = http.client.HTTPSConnection(hostname)
31-
connection.request("GET", "/")
32+
connection.request("GET", endpoint)
3233
response = connection.getresponse()
3334
return response.status
3435

@@ -101,19 +102,31 @@ def main(event, context):
101102
'tls_1_1_cipher_suites,tls_1_2_cipher_suites,tls_1_3_cipher_suites'
102103
).replace(' ', '').split(',')).union({'certificate_info'})
103104
logger.info('Configuration is OK')
105+
logger.info(f'Going to check: {hostnames}')
104106
servers_to_scan = []
105107
# First validate that we can connect to the servers we want to scan
106108
for hostname in hostnames:
107109
# DNS check. Try to resolve hostname.
108110
try:
109-
logger.debug(f'DNS: {hostname} - Testing...')
110-
server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(hostname, 443)
111-
logger.debug(f'DNS: {hostname} - OK')
111+
# for urlparse to correctly parse the address it needs a scheme in fron of the domain name
112+
# otherwise it might get confused
113+
hostname_with_scheme = hostname
114+
if not hostname_with_scheme.startswith('https://'):
115+
hostname_with_scheme = f'https://{hostname}'
116+
logger.debug(f'prepend scheme to {hostname} so it is {hostname_with_scheme}')
117+
hostname_parsed = urlparse(hostname_with_scheme)
118+
logger.debug(f'hostname pasrsing result: {hostname_parsed}')
119+
path = "/" if hostname_parsed.path == "" else hostname_parsed.path
120+
host = hostname_parsed.netloc
121+
logger.debug(f'parsed {hostname} to host {host} and path {path}')
122+
logger.debug(f'DNS: {host} - Testing...')
123+
server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(host, 443)
124+
logger.debug(f'DNS: {host} - OK')
112125
# Connection check. Try to connect to hostname.
113126
try:
114127
logger.debug(f'Connect: {hostname} - Testing...')
115128
server_info = ServerConnectivityTester().perform(server_location)
116-
response_status = get_response_status(hostname)
129+
response_status = get_response_status(host, path)
117130
if response_status not in health_check_matcher:
118131
raise ConnectionToServerFailed(server_info.server_location, server_info.network_configuration,
119132
error_message=f'HTTP Error. Status code: {response_status}')

0 commit comments

Comments
 (0)