{"id":15481863,"url":"https://github.com/toolisticon/ssl-hostinfo-prometheus-exporter","last_synced_at":"2025-10-03T13:35:18.185Z","repository":{"id":34068354,"uuid":"166549614","full_name":"toolisticon/ssl-hostinfo-prometheus-exporter","owner":"toolisticon","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-09T03:45:08.000Z","size":21611,"stargazers_count":9,"open_issues_count":13,"forks_count":1,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-04-14T03:15:31.167Z","etag":null,"topics":["grafana","prometheus","prometheus-exporter","ssl-certificates"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toolisticon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":null},"created_at":"2019-01-19T13:26:55.000Z","updated_at":"2025-04-08T23:06:49.000Z","dependencies_parsed_at":"2024-01-15T07:05:08.569Z","dependency_job_id":"6a77ea91-f37f-405b-8167-b0000b5f72e6","html_url":"https://github.com/toolisticon/ssl-hostinfo-prometheus-exporter","commit_stats":{"total_commits":678,"total_committers":7,"mean_commits":96.85714285714286,"dds":0.6769911504424779,"last_synced_commit":"cef04e17fa8765e82233611b5f60c44c6cd1f2f0"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolisticon%2Fssl-hostinfo-prometheus-exporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolisticon%2Fssl-hostinfo-prometheus-exporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolisticon%2Fssl-hostinfo-prometheus-exporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolisticon%2Fssl-hostinfo-prometheus-exporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toolisticon","download_url":"https://codeload.github.com/toolisticon/ssl-hostinfo-prometheus-exporter/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248813803,"owners_count":21165634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grafana","prometheus","prometheus-exporter","ssl-certificates"],"created_at":"2024-10-02T05:06:39.074Z","updated_at":"2025-10-03T13:35:13.119Z","avatar_url":"https://github.com/toolisticon.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Monitor SSL certificates in Prometheus\n\n[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE)\n[![CI](https://github.com/toolisticon/ssl-hostinfo-prometheus-exporter/actions/workflows/build.yml/badge.svg)](https://github.com/toolisticon/ssl-hostinfo-prometheus-exporter/actions/workflows/build.yml)\n[![Build Status](https://travis-ci.org/toolisticon/ssl-hostinfo-prometheus-exporter.svg?branch=master)](https://travis-ci.org/toolisticon/ssl-hostinfo-prometheus-exporter)\n[![Docker Build Status](https://img.shields.io/docker/automated/toolisticon/ssl-hostinfo-prometheus-exporter.svg)](https://hub.docker.com/r/toolisticon/ssl-hostinfo-prometheus-exporter/)\n[![npm version](https://badge.fury.io/js/%40toolisticon%2Fssl-hostinfo-prometheus-exporter.svg)](https://badge.fury.io/js/%40toolisticon%2Fssl-hostinfo-prometheus-exporter)\n[![npm downloads](https://img.shields.io/npm/dm/%40toolisticon%2Fssl-hostinfo-prometheus-exporter.svg)](https://www.npmjs.com/package/%40toolisticon%2Fssl-hostinfo-prometheus-exporter)\n[![npm downloads](https://img.shields.io/npm/dt/%40toolisticon%2Fssl-hostinfo-prometheus-exporter.svg)](https://www.npmjs.com/package/%40toolisticon%2Fssl-hostinfo-prometheus-exporter)\n[![Docker Stars](https://img.shields.io/docker/stars/toolisticon/ssl-hostinfo-prometheus-exporter.svg)](https://hub.docker.com/r/toolisticon/ssl-hostinfo-prometheus-exporter/)\n[![Known Vulnerabilities](https://snyk.io/test/github/toolisticon/ssl-hostinfo-prometheus-exporter/badge.svg)](https://snyk.io/test/github/toolisticon/ssl-hostinfo-prometheus-exporter)\n\n## Usage\n\nInstall the app first\n```\nnpm i -g @toolisticon/ssl-hostinfo-prometheus-exporter\n```\n\nThis nodejs application assumes that you define a list of urls to check via environment variables:\n\n```\nexport URLS_TO_CHECK=app1.sample.com,app2.sample.com\nssl-hostinfo-prom\n```\n\n## Sample Values\n\nThe metrics are available via via localhost:9000 :\n\n```\nsecurity_ssl_mozilla_observatory{algorithm_version=\"2\",end_time=\"1547804767000\",grade=\"D\",hidden=\"false\",likelihood_indicator=\"MEDIUM\",response_headers_cache-control=\"no-cache, no-store, max-age=0, must-revalidate\",response_headers_content-type=\"996616800000\",response_headers_date=\"1547804765000\",response_headers_expires=\"946681200000\",response_headers_pragma=\"no-cache\",response_headers_set-cookie=\"556448b8f044ea9c0fe56ec8eabb3577=6dda08a289298b570c8daa5a12e94408; path=/; HttpOnly; Secure\",response_headers_transfer-encoding=\"chunked\",response_headers_x-application-context=\"193033926000000\",response_headers_x-content-type-options=\"nosniff\",response_headers_x-xss-protection=\"1; mode=block\",scan_id=\"9783173\",score=\"35\",start_time=\"1547804762000\",state=\"FINISHED\",status_code=\"404\",tests_failed=\"3\",tests_passed=\"9\",tests_quantity=\"12\",url=\"sub.domain-sample.com\",security_ssl_mozilla_observatory{algorithm_version=\"2\",end_time=\"1547804767000\",grade=\"D\",hidden=\"false\",likelihood_indicator=\"MEDIUM\",response_headers_cache-control=\"no-cache, no-store, max-age=0, must-revalidate\",response_headers_content-type=\"996616800000\",response_headers_date=\"1547804765000\",response_headers_expires=\"946681200000\",response_headers_pragma=\"no-cache\",response_headers_set-cookie=\"556448b8f044ea9c0fe56ec8eabb3577=6dda08a289298b570c8daa5a12e94408; path=/; HttpOnly; Secure\",response_headers_transfer-encoding=\"chunked\",response_headers_x-application-context=\"193033926000000\",response_headers_x-content-type-options=\"nosniff\",response_headers_x-xss-protection=\"1; mode=block\",scan_id=\"9783173\",score=\"35\",start_time=\"1547804762000\",state=\"FINISHED\",status_code=\"404\",tests_failed=\"3\",tests_passed=\"9\",tests_quantity=\"12\",url=\"sub1.domain-sample.com\",} 35\nsecurity_ssl_mozilla_observatory{algorithm_version=\"2\",end_time=\"1547804767000\",grade=\"D\",hidden=\"false\",likelihood_indicator=\"MEDIUM\",response_headers_cache-control=\"no-cache, no-store, max-age=0, must-revalidate\",response_headers_content-type=\"996616800000\",response_headers_date=\"1547804765000\",response_headers_expires=\"946681200000\",response_headers_pragma=\"no-cache\",response_headers_set-cookie=\"556448b8f044ea9c0fe56ec8eabb3577=6dda08a289298b570c8daa5a12e94408; path=/; HttpOnly; Secure\",response_headers_transfer-encoding=\"chunked\",response_headers_x-application-context=\"193033926000000\",response_headers_x-content-type-options=\"nosniff\",response_headers_x-xss-protection=\"1; mode=block\",scan_id=\"9783173\",score=\"35\",start_time=\"1547804762000\",state=\"FINISHED\",status_code=\"404\",tests_failed=\"3\",tests_passed=\"9\",tests_quantity=\"12\",url=\"sub.domain-sample.com\",security_ssl_mozilla_observatory{algorithm_version=\"2\",end_time=\"1547804767000\",grade=\"D\",hidden=\"false\",likelihood_indicator=\"MEDIUM\",response_headers_cache-control=\"no-cache, no-store, max-age=0, must-revalidate\",response_headers_content-type=\"996616800000\",response_headers_date=\"1547804765000\",response_headers_expires=\"946681200000\",response_headers_pragma=\"no-cache\",response_headers_set-cookie=\"556448b8f044ea9c0fe56ec8eabb3577=6dda08a289298b570c8daa5a12e94408; path=/; HttpOnly; Secure\",response_headers_transfer-encoding=\"chunked\",response_headers_x-application-context=\"193033926000000\",response_headers_x-content-type-options=\"nosniff\",response_headers_x-xss-protection=\"1; mode=block\",scan_id=\"9783173\",score=\"35\",start_time=\"1547804762000\",state=\"FINISHED\",status_code=\"404\",tests_failed=\"3\",tests_passed=\"9\",tests_quantity=\"12\",url=\"sub2.domain-sample.com\",} 35\n```\n\n[Here](https://grafana.com/dashboards/10144) you'll find a sample dashboard.\n\n## Configuration\n\nYou can override the config via environment variables:\n```\n   URLS_TO_CHECK: // list of urls\n   SERVER_PORT: // set desired port for prometheus endpoint, defaults to 9000\n   CRON: // set cron pattern, default is '0 0 * * * *',\n   LOG_LEVEL: // set log level, default is 'ERROR' ('INFO' outputs details info),\n   CONSOLE_LOG: // set to true to omit logging to file, otherwise logs will be written to `logs` dir\n```\n\nSample:\n```\nURLS_TO_CHECK=url1.sample.com,url2.sample.com:8443 LOG_LEVEL=INFO CONSOLE_LOG=true node app.js\n```\nWill produce the following output:\n```\n{\"pid\":65072,\"msg\":\"[log4bro] Logger is: in-prod=false, in-docker:true, level=DEBUG, skipDebug=false\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.443Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Start reading route information.\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.563Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Triggering scan for url1.sample.com,url2.sample.com\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.563Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Triggering scan for url1.sample.com\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.563Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Triggering scan for url2.sample.com\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.566Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"prometheus-exporter listening at 9000\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.569Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Reading scan results for url1.sample.com\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.769Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Reading scan results for url2.sample.com\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:20.770Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Skipping invalid response for mozilla scoring\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:21.206Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n{\"pid\":65072,\"msg\":\"Skipping invalid response for mozilla scoring\",\"loglevel\":\"INFO\",\"loglevel_value\":30,\"@timestamp\":\"2019-04-02T13:56:21.208Z\",\"host\":\"MPB-M1.local\",\"log_type\":\"application\",\"application_type\":\"service\"}\n```\n\nAnd\n```\nURLS_TO_CHECK=url1.sample.com,url2.sample.com LOG_LEVEL=INFO node app.js\n```\ncreates this output:\n```\nINFO @ 2019-04-02T13:57:42.181Z : [log4bro] Logger is: in-prod=false, in-docker:false, level=DEBUG, skipDebug=false\nINFO @ 2019-04-02T13:57:42.301Z : Start reading route information.\nINFO @ 2019-04-02T13:57:42.301Z : Triggering scan for url1.sample.com,url2.sample.com\nINFO @ 2019-04-02T13:57:42.301Z : Triggering scan for url1.sample.com\nINFO @ 2019-04-02T13:57:42.304Z : Triggering scan for url2.sample.com\nINFO @ 2019-04-02T13:57:42.307Z : prometheus-exporter listening at 9000\nINFO @ 2019-04-02T13:57:42.507Z : Reading scan results for url1.sample.com\nINFO @ 2019-04-02T13:57:42.508Z : Reading scan results for url2.sample.com\nINFO @ 2019-04-02T13:57:43.001Z : Skipping invalid response for mozilla scoring\nINFO @ 2019-04-02T13:57:43.024Z : Skipping invalid response for mozilla scoring\n```\nand the logs in JSON format within the directy `logs`\n\n\u003eNOTE: You can omit the port, it will default to 443.\n\n## Troubleshooting\n\nTBD\n\n## Development\n\n### Usage as library\n\nThe package can be also used as a dependency:\n\n\n```\nnpm i @toolisticon/ssl-hostinfo-prometheus-exporter\n```\n\nIn your app you can use then the api:\n\n```\nconst updateRoutesInfo = require('@toolisticon/ssl-hostinfo-prometheus-exporter').updateRoutesInfo;\nconst startPrometheusListener = require('@toolisticon/ssl-hostinfo-prometheus-exporter').startPrometheusListener;\n\n// trigger one update immediatly\ntriggerUpdate();\n\nstartPrometheusListener();\n\n```\n\n\n### Debug\n\nTo debug run the following command:\n```\nnode --inspect-brk index.js\n```\n\nTo debug unit tests:\n\n```\nnpm run test:debug\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolisticon%2Fssl-hostinfo-prometheus-exporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoolisticon%2Fssl-hostinfo-prometheus-exporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolisticon%2Fssl-hostinfo-prometheus-exporter/lists"}