fluent-plugin-ssl-check 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitlab-ci.yml +10 -0
 - data/.rubocop.yml +4 -0
 - data/.ruby-version +1 -1
 - data/Gemfile.lock +5 -1
 - data/README.md +80 -0
 - data/fluent-plugin-ssl-check.gemspec +2 -1
 - data/lib/fluent/plugin/in_ssl_check.rb +8 -112
 - data/lib/fluent/plugin/in_ssl_file_check.rb +104 -0
 - data/lib/fluent/plugin/ssl_check/file_checker.rb +51 -0
 - data/lib/fluent/plugin/ssl_check/ssl_common.rb +19 -0
 - data/lib/fluent/plugin/ssl_check/ssl_info.rb +75 -0
 - data/lib/fluent/plugin/ssl_check/ssl_input_emit.rb +63 -0
 - data/lib/fluent/plugin/ssl_check.rb +13 -0
 - metadata +30 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 32576d289dd8aa0e769f4e4aaa975cbc0517d3d25a70506f5ef478572ca7cf89
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: ac1682153f0c68ed33aec0ad1334776425d542369fa0285a6c306dc1892c72e2
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b4702ea39635a4f00dce824ca750a5c9b507a1102234b88b3fe782bd25205c7377a40cde8e51143324af1d1f25ee574542e391b8e99f59e9c3fa1d31b15d95cc
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: e67001eedef2c25b144ef2f7f63b6af0824279fb84ecbe9bda90005627bd575c1558b69027ec80944804f08f1840f162f65276464e743b41c087e1515d7789fe
         
     | 
    
        data/.gitlab-ci.yml
    ADDED
    
    
    
        data/.rubocop.yml
    CHANGED
    
    | 
         @@ -22,6 +22,7 @@ Metrics/ClassLength: 
     | 
|
| 
       22 
22 
     | 
    
         
             
              Exclude:
         
     | 
| 
       23 
23 
     | 
    
         
             
                - test/**/*.rb
         
     | 
| 
       24 
24 
     | 
    
         
             
                - lib/fluent/plugin/in_ssl_check.rb
         
     | 
| 
      
 25 
     | 
    
         
            +
                - lib/fluent/plugin/in_ssl_file_check.rb
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
27 
     | 
    
         
             
            Metrics/MethodLength:
         
     | 
| 
       27 
28 
     | 
    
         
             
              Max: 20
         
     | 
| 
         @@ -29,3 +30,6 @@ Metrics/MethodLength: 
     | 
|
| 
       29 
30 
     | 
    
         
             
            # Naming/MethodParameterName:
         
     | 
| 
       30 
31 
     | 
    
         
             
            #   Exclude:
         
     | 
| 
       31 
32 
     | 
    
         
             
            #     - lib/fluent/plugin/in_ssl_check.rb
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            Style/Documentation:
         
     | 
| 
      
 35 
     | 
    
         
            +
              Enabled: false
         
     | 
    
        data/.ruby-version
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            3.3.6
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            PATH
         
     | 
| 
       2 
2 
     | 
    
         
             
              remote: .
         
     | 
| 
       3 
3 
     | 
    
         
             
              specs:
         
     | 
| 
       4 
     | 
    
         
            -
                fluent-plugin-ssl-check (2. 
     | 
| 
      
 4 
     | 
    
         
            +
                fluent-plugin-ssl-check (2.4.0)
         
     | 
| 
       5 
5 
     | 
    
         
             
                  fluentd (>= 0.14.10, < 2)
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            GEM
         
     | 
| 
         @@ -29,6 +29,8 @@ GEM 
     | 
|
| 
       29 
29 
     | 
    
         
             
                json (2.6.3)
         
     | 
| 
       30 
30 
     | 
    
         
             
                kwalify (0.7.2)
         
     | 
| 
       31 
31 
     | 
    
         
             
                language_server-protocol (3.17.0.3)
         
     | 
| 
      
 32 
     | 
    
         
            +
                mocha (2.6.1)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  ruby2_keywords (>= 0.0.5)
         
     | 
| 
       32 
34 
     | 
    
         
             
                msgpack (1.7.2)
         
     | 
| 
       33 
35 
     | 
    
         
             
                parallel (1.23.0)
         
     | 
| 
       34 
36 
     | 
    
         
             
                parser (3.2.2.3)
         
     | 
| 
         @@ -61,6 +63,7 @@ GEM 
     | 
|
| 
       61 
63 
     | 
    
         
             
                rubocop-rake (0.6.0)
         
     | 
| 
       62 
64 
     | 
    
         
             
                  rubocop (~> 1.0)
         
     | 
| 
       63 
65 
     | 
    
         
             
                ruby-progressbar (1.13.0)
         
     | 
| 
      
 66 
     | 
    
         
            +
                ruby2_keywords (0.0.5)
         
     | 
| 
       64 
67 
     | 
    
         
             
                serverengine (2.3.2)
         
     | 
| 
       65 
68 
     | 
    
         
             
                  sigdump (~> 0.2.2)
         
     | 
| 
       66 
69 
     | 
    
         
             
                sigdump (0.2.5)
         
     | 
| 
         @@ -84,6 +87,7 @@ DEPENDENCIES 
     | 
|
| 
       84 
87 
     | 
    
         
             
              bundler (~> 2.4)
         
     | 
| 
       85 
88 
     | 
    
         
             
              byebug (~> 11.1, >= 11.1.3)
         
     | 
| 
       86 
89 
     | 
    
         
             
              fluent-plugin-ssl-check!
         
     | 
| 
      
 90 
     | 
    
         
            +
              mocha (~> 2.6, >= 2.6.1)
         
     | 
| 
       87 
91 
     | 
    
         
             
              rake (~> 13.0, >= 13.0.6)
         
     | 
| 
       88 
92 
     | 
    
         
             
              reek (~> 6.1, >= 6.1.4)
         
     | 
| 
       89 
93 
     | 
    
         
             
              rubocop (~> 1.56)
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -2,6 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            [Fluentd](https://fluentd.org/) input plugin to check ssl service.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       5 
6 
     | 
    
         
             
            ## plugins
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            ### in - ssl_check
         
     | 
| 
         @@ -35,6 +36,7 @@ Options are: 
     | 
|
| 
       35 
36 
     | 
    
         
             
            * cert: client cert for ssl connection
         
     | 
| 
       36 
37 
     | 
    
         
             
            * key: client key associated to client cert for ssl connection
         
     | 
| 
       37 
38 
     | 
    
         
             
            * timeout: timeout for ssl check execution (5sec)
         
     | 
| 
      
 39 
     | 
    
         
            +
            * paths: local certificate file paths
         
     | 
| 
       38 
40 
     | 
    
         
             
            * log_events: emit log format (true)
         
     | 
| 
       39 
41 
     | 
    
         
             
            * metric_events: emit metric format (false)
         
     | 
| 
       40 
42 
     | 
    
         
             
            * event_prefix: metric event prefix for extra dimension
         
     | 
| 
         @@ -42,6 +44,84 @@ Options are: 
     | 
|
| 
       42 
44 
     | 
    
         | 
| 
       43 
45 
     | 
    
         
             
            If no port is specified with host, default port is 443.
         
     | 
| 
       44 
46 
     | 
    
         | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            ### in - ssl_file_check
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            Poll ssl local file and report status.
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            Example:
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ``` conf
         
     | 
| 
      
 55 
     | 
    
         
            +
            <source>
         
     | 
| 
      
 56 
     | 
    
         
            +
              @type ssl_file_check
         
     | 
| 
      
 57 
     | 
    
         
            +
              tag ssl_check
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              paths /etc/cert/host.pem,/app/application_1/cert.pem
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              interval 600
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              ca_path /my/ca_dir/
         
     | 
| 
      
 64 
     | 
    
         
            +
              ca_file /my/ca_file
         
     | 
| 
      
 65 
     | 
    
         
            +
            </source>
         
     | 
| 
      
 66 
     | 
    
         
            +
            ```
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            Options are:
         
     | 
| 
      
 69 
     | 
    
         
            +
            * tag: Tag to emit events on
         
     | 
| 
      
 70 
     | 
    
         
            +
            * interval: check every X seconds
         
     | 
| 
      
 71 
     | 
    
         
            +
            * paths: local certificate file paths
         
     | 
| 
      
 72 
     | 
    
         
            +
            * ca_path: directory that contains CA files
         
     | 
| 
      
 73 
     | 
    
         
            +
            * ca_file: specify a CA file directly
         
     | 
| 
      
 74 
     | 
    
         
            +
            * log_events: emit log format (true)
         
     | 
| 
      
 75 
     | 
    
         
            +
            * metric_events: emit metric format (false)
         
     | 
| 
      
 76 
     | 
    
         
            +
            * event_prefix: metric event prefix for extra dimension
         
     | 
| 
      
 77 
     | 
    
         
            +
            * timestamp_format: iso, epochmillis timestamp format (iso)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            ## output examples
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            ### log output example
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            ``` json
         
     | 
| 
      
 85 
     | 
    
         
            +
            {
         
     | 
| 
      
 86 
     | 
    
         
            +
                "timestamp": "2023-10-03T09:59:41.580+02:00",
         
     | 
| 
      
 87 
     | 
    
         
            +
                "status": 1,
         
     | 
| 
      
 88 
     | 
    
         
            +
                "host": "www.google.fr",
         
     | 
| 
      
 89 
     | 
    
         
            +
                "port": 443,
         
     | 
| 
      
 90 
     | 
    
         
            +
                "ssl_version": "TLSv1.2",
         
     | 
| 
      
 91 
     | 
    
         
            +
                "ssl_dn": "/CN=*.google.fr",
         
     | 
| 
      
 92 
     | 
    
         
            +
                "ssl_not_after": "2023-11-27T08:25:08.000Z",
         
     | 
| 
      
 93 
     | 
    
         
            +
                "expire_in_days": 55,
         
     | 
| 
      
 94 
     | 
    
         
            +
                "serial": "4e79dbb13c6b57b309780da2d1edbda4"
         
     | 
| 
      
 95 
     | 
    
         
            +
            }
         
     | 
| 
      
 96 
     | 
    
         
            +
            ```
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            ### metric output example
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            ``` json
         
     | 
| 
      
 101 
     | 
    
         
            +
            {
         
     | 
| 
      
 102 
     | 
    
         
            +
                "timestamp": "2023-10-03T10:06:21.417+02:00",
         
     | 
| 
      
 103 
     | 
    
         
            +
                "metric_name": "ssl_status",
         
     | 
| 
      
 104 
     | 
    
         
            +
                "metric_value": 1,
         
     | 
| 
      
 105 
     | 
    
         
            +
                "host": "www.google.fr",
         
     | 
| 
      
 106 
     | 
    
         
            +
                "port": 443,
         
     | 
| 
      
 107 
     | 
    
         
            +
                "ssl_dn": "/CN=*.google.fr",
         
     | 
| 
      
 108 
     | 
    
         
            +
                "ssl_version": "TLSv1.2",
         
     | 
| 
      
 109 
     | 
    
         
            +
                "ssl_not_after": "2023-11-27T08:25:08.000Z",
         
     | 
| 
      
 110 
     | 
    
         
            +
                "serial": "4e79dbb13c6b57b309780da2d1edbda4"
         
     | 
| 
      
 111 
     | 
    
         
            +
            }
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            {
         
     | 
| 
      
 114 
     | 
    
         
            +
                "timestamp": "2023-10-03T10:06:21.417+02:00",
         
     | 
| 
      
 115 
     | 
    
         
            +
                "metric_name": "ssl_expirency",
         
     | 
| 
      
 116 
     | 
    
         
            +
                "metric_value": 55,
         
     | 
| 
      
 117 
     | 
    
         
            +
                "host": "www.google.fr",
         
     | 
| 
      
 118 
     | 
    
         
            +
                "port": 443,
         
     | 
| 
      
 119 
     | 
    
         
            +
                "ssl_dn": "/CN=*.google.fr",
         
     | 
| 
      
 120 
     | 
    
         
            +
                "serial": "4e79dbb13c6b57b309780da2d1edbda4"
         
     | 
| 
      
 121 
     | 
    
         
            +
            }
         
     | 
| 
      
 122 
     | 
    
         
            +
            ```
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
       45 
125 
     | 
    
         
             
            ## Installation
         
     | 
| 
       46 
126 
     | 
    
         | 
| 
       47 
127 
     | 
    
         
             
            Manual install, by executing:
         
     | 
| 
         @@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            Gem::Specification.new do |spec|
         
     | 
| 
       7 
7 
     | 
    
         
             
              spec.name    = 'fluent-plugin-ssl-check'
         
     | 
| 
       8 
     | 
    
         
            -
              spec.version = '2. 
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version = '2.4.0'
         
     | 
| 
       9 
9 
     | 
    
         
             
              spec.authors = ['Thomas Tych']
         
     | 
| 
       10 
10 
     | 
    
         
             
              spec.email   = ['thomas.tych@gmail.com']
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -27,6 +27,7 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       27 
27 
     | 
    
         
             
              spec.add_development_dependency 'bump', '~> 0.10.0'
         
     | 
| 
       28 
28 
     | 
    
         
             
              spec.add_development_dependency 'bundler', '~> 2.4'
         
     | 
| 
       29 
29 
     | 
    
         
             
              spec.add_development_dependency 'byebug', '~> 11.1', '>= 11.1.3'
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_development_dependency 'mocha', '~> 2.6', '>= 2.6.1'
         
     | 
| 
       30 
31 
     | 
    
         
             
              spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.6'
         
     | 
| 
       31 
32 
     | 
    
         
             
              spec.add_development_dependency 'reek', '~> 6.1', '>= 6.1.4'
         
     | 
| 
       32 
33 
     | 
    
         
             
              spec.add_development_dependency 'rubocop', '~> 1.56'
         
     | 
| 
         @@ -23,15 +23,17 @@ require 'timeout' 
     | 
|
| 
       23 
23 
     | 
    
         
             
            require 'date'
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
            require_relative 'extensions/time'
         
     | 
| 
      
 26 
     | 
    
         
            +
            require_relative 'ssl_check'
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
       27 
28 
     | 
    
         
             
            module Fluent
         
     | 
| 
       28 
29 
     | 
    
         
             
              module Plugin
         
     | 
| 
       29 
     | 
    
         
            -
                # ssl_check input plugin
         
     | 
| 
       30 
     | 
    
         
            -
                #   check ssl service
         
     | 
| 
       31 
30 
     | 
    
         
             
                class SslCheckInput < Fluent::Plugin::Input
         
     | 
| 
       32 
31 
     | 
    
         
             
                  NAME = 'ssl_check'
         
     | 
| 
       33 
32 
     | 
    
         
             
                  Fluent::Plugin.register_input(NAME, self)
         
     | 
| 
       34 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
                  include Fluent::Plugin::SslCheck::SslInputEmit
         
     | 
| 
      
 35 
     | 
    
         
            +
                  include Fluent::Plugin::SslCheck::SslCommon
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       35 
37 
     | 
    
         
             
                  DEFAULT_TAG = NAME
         
     | 
| 
       36 
38 
     | 
    
         
             
                  DEFAULT_PORT = 443
         
     | 
| 
       37 
39 
     | 
    
         
             
                  DEFAULT_INTERVAL = 600
         
     | 
| 
         @@ -41,6 +43,7 @@ module Fluent 
     | 
|
| 
       41 
43 
     | 
    
         
             
                  DEFAULT_LOG_EVENTS = true
         
     | 
| 
       42 
44 
     | 
    
         
             
                  DEFAULT_METRIC_EVENTS = false
         
     | 
| 
       43 
45 
     | 
    
         
             
                  DEFAULT_EVENT_PREFIX = ''
         
     | 
| 
      
 46 
     | 
    
         
            +
                  DEFAULT_TIMESTAMP_FORMAT = :iso
         
     | 
| 
       44 
47 
     | 
    
         | 
| 
       45 
48 
     | 
    
         
             
                  desc 'Tag to emit events on'
         
     | 
| 
       46 
49 
     | 
    
         
             
                  config_param :tag, :string, default: DEFAULT_TAG
         
     | 
| 
         @@ -72,7 +75,7 @@ module Fluent 
     | 
|
| 
       72 
75 
     | 
    
         
             
                  desc 'Event prefix'
         
     | 
| 
       73 
76 
     | 
    
         
             
                  config_param :event_prefix, :string, default: DEFAULT_EVENT_PREFIX
         
     | 
| 
       74 
77 
     | 
    
         
             
                  desc 'Timestamp format'
         
     | 
| 
       75 
     | 
    
         
            -
                  config_param :timestamp_format, :enum, list: %i[iso epochmillis], default:  
     | 
| 
      
 78 
     | 
    
         
            +
                  config_param :timestamp_format, :enum, list: %i[iso epochmillis], default: DEFAULT_TIMESTAMP_FORMAT
         
     | 
| 
       76 
79 
     | 
    
         | 
| 
       77 
80 
     | 
    
         
             
                  helpers :timer
         
     | 
| 
       78 
81 
     | 
    
         | 
| 
         @@ -125,54 +128,6 @@ module Fluent 
     | 
|
| 
       125 
128 
     | 
    
         
             
                    ssl_client.ssl_info
         
     | 
| 
       126 
129 
     | 
    
         
             
                  end
         
     | 
| 
       127 
130 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
                  def emit_logs(ssl_info)
         
     | 
| 
       129 
     | 
    
         
            -
                    record = {
         
     | 
| 
       130 
     | 
    
         
            -
                      'timestamp' => ssl_info.time.send("to_#{timestamp_format}"),
         
     | 
| 
       131 
     | 
    
         
            -
                      'status' => ssl_info.status,
         
     | 
| 
       132 
     | 
    
         
            -
                      'host' => ssl_info.host,
         
     | 
| 
       133 
     | 
    
         
            -
                      'port' => ssl_info.port,
         
     | 
| 
       134 
     | 
    
         
            -
                      'ssl_version' => ssl_info.ssl_version,
         
     | 
| 
       135 
     | 
    
         
            -
                      'ssl_dn' => ssl_info.subject_s,
         
     | 
| 
       136 
     | 
    
         
            -
                      'ssl_not_after' => ssl_info.not_after,
         
     | 
| 
       137 
     | 
    
         
            -
                      'expire_in_days' => ssl_info.expire_in_days
         
     | 
| 
       138 
     | 
    
         
            -
                    }
         
     | 
| 
       139 
     | 
    
         
            -
                    record.update('error_class' => ssl_info.error_class) if ssl_info.error_class
         
     | 
| 
       140 
     | 
    
         
            -
                    router.emit(tag, Fluent::EventTime.from_time(ssl_info.time), record)
         
     | 
| 
       141 
     | 
    
         
            -
                  end
         
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
                  def emit_metrics(ssl_info)
         
     | 
| 
       144 
     | 
    
         
            -
                    emit_metric_status(ssl_info)
         
     | 
| 
       145 
     | 
    
         
            -
                    emit_metric_expirency(ssl_info)
         
     | 
| 
       146 
     | 
    
         
            -
                  end
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
                  def emit_metric_status(ssl_info)
         
     | 
| 
       149 
     | 
    
         
            -
                    record = {
         
     | 
| 
       150 
     | 
    
         
            -
                      'timestamp' => ssl_info.time.send("to_#{timestamp_format}"),
         
     | 
| 
       151 
     | 
    
         
            -
                      'metric_name' => 'ssl_status',
         
     | 
| 
       152 
     | 
    
         
            -
                      'metric_value' => ssl_info.status,
         
     | 
| 
       153 
     | 
    
         
            -
                      "#{event_prefix}host" => ssl_info.host,
         
     | 
| 
       154 
     | 
    
         
            -
                      "#{event_prefix}port" => ssl_info.port,
         
     | 
| 
       155 
     | 
    
         
            -
                      "#{event_prefix}ssl_dn" => ssl_info.subject_s,
         
     | 
| 
       156 
     | 
    
         
            -
                      "#{event_prefix}ssl_version" => ssl_info.ssl_version,
         
     | 
| 
       157 
     | 
    
         
            -
                      "#{event_prefix}ssl_not_after" => ssl_info.not_after
         
     | 
| 
       158 
     | 
    
         
            -
                    }
         
     | 
| 
       159 
     | 
    
         
            -
                    router.emit(tag, Fluent::EventTime.from_time(ssl_info.time), record)
         
     | 
| 
       160 
     | 
    
         
            -
                  end
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                  def emit_metric_expirency(ssl_info)
         
     | 
| 
       163 
     | 
    
         
            -
                    return if ssl_info.error
         
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                    record = {
         
     | 
| 
       166 
     | 
    
         
            -
                      'timestamp' => ssl_info.time.send("to_#{timestamp_format}"),
         
     | 
| 
       167 
     | 
    
         
            -
                      'metric_name' => 'ssl_expirency',
         
     | 
| 
       168 
     | 
    
         
            -
                      'metric_value' => ssl_info.expire_in_days,
         
     | 
| 
       169 
     | 
    
         
            -
                      "#{event_prefix}host" => ssl_info.host,
         
     | 
| 
       170 
     | 
    
         
            -
                      "#{event_prefix}port" => ssl_info.port,
         
     | 
| 
       171 
     | 
    
         
            -
                      "#{event_prefix}ssl_dn" => ssl_info.subject_s
         
     | 
| 
       172 
     | 
    
         
            -
                    }
         
     | 
| 
       173 
     | 
    
         
            -
                    router.emit(tag, Fluent::EventTime.from_time(ssl_info.time), record)
         
     | 
| 
       174 
     | 
    
         
            -
                  end
         
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
131 
     | 
    
         
             
                  private
         
     | 
| 
       177 
132 
     | 
    
         | 
| 
       178 
133 
     | 
    
         
             
                  def ssl_verify_mode
         
     | 
| 
         @@ -181,57 +136,6 @@ module Fluent 
     | 
|
| 
       181 
136 
     | 
    
         
             
                    OpenSSL::SSL::VERIFY_NONE
         
     | 
| 
       182 
137 
     | 
    
         
             
                  end
         
     | 
| 
       183 
138 
     | 
    
         | 
| 
       184 
     | 
    
         
            -
                  # ssl info
         
     | 
| 
       185 
     | 
    
         
            -
                  #  to encapsulate extracted ssl information
         
     | 
| 
       186 
     | 
    
         
            -
                  class SslInfo
         
     | 
| 
       187 
     | 
    
         
            -
                    OK = 1
         
     | 
| 
       188 
     | 
    
         
            -
                    KO = 0
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
                    attr_reader :time
         
     | 
| 
       191 
     | 
    
         
            -
                    attr_accessor :host, :port, :cert, :cert_chain, :ssl_version, :error
         
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
                    # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       194 
     | 
    
         
            -
                    def initialize(host: nil, port: nil, cert: nil, cert_chain: nil, ssl_version: nil, error: nil, time: Time.now)
         
     | 
| 
       195 
     | 
    
         
            -
                      @host = host
         
     | 
| 
       196 
     | 
    
         
            -
                      @port = port
         
     | 
| 
       197 
     | 
    
         
            -
                      @cert = cert
         
     | 
| 
       198 
     | 
    
         
            -
                      @cert_chain = cert_chain
         
     | 
| 
       199 
     | 
    
         
            -
                      @ssl_version = ssl_version
         
     | 
| 
       200 
     | 
    
         
            -
                      @error = error
         
     | 
| 
       201 
     | 
    
         
            -
                      @time = time
         
     | 
| 
       202 
     | 
    
         
            -
                    end
         
     | 
| 
       203 
     | 
    
         
            -
                    # rubocop:enable Metrics/ParameterLists
         
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
                    def subject_s
         
     | 
| 
       206 
     | 
    
         
            -
                      cert.subject.to_s if cert&.subject
         
     | 
| 
       207 
     | 
    
         
            -
                    end
         
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
                    def expire_in_days
         
     | 
| 
       210 
     | 
    
         
            -
                      return unless cert&.not_after
         
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
                      expire_in = cert.not_after
         
     | 
| 
       213 
     | 
    
         
            -
                      ((expire_in - time) / 3600 / 24).to_i
         
     | 
| 
       214 
     | 
    
         
            -
                    end
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
                    def not_after
         
     | 
| 
       217 
     | 
    
         
            -
                      return unless cert
         
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
                      cert.not_after.iso8601(3)
         
     | 
| 
       220 
     | 
    
         
            -
                    end
         
     | 
| 
       221 
     | 
    
         
            -
             
     | 
| 
       222 
     | 
    
         
            -
                    def status
         
     | 
| 
       223 
     | 
    
         
            -
                      return KO if error
         
     | 
| 
       224 
     | 
    
         
            -
             
     | 
| 
       225 
     | 
    
         
            -
                      OK
         
     | 
| 
       226 
     | 
    
         
            -
                    end
         
     | 
| 
       227 
     | 
    
         
            -
             
     | 
| 
       228 
     | 
    
         
            -
                    def error_class
         
     | 
| 
       229 
     | 
    
         
            -
                      return unless error
         
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
                      error.class.to_s
         
     | 
| 
       232 
     | 
    
         
            -
                    end
         
     | 
| 
       233 
     | 
    
         
            -
                  end
         
     | 
| 
       234 
     | 
    
         
            -
             
     | 
| 
       235 
139 
     | 
    
         
             
                  # ssl client
         
     | 
| 
       236 
140 
     | 
    
         
             
                  #  to check ssl status
         
     | 
| 
       237 
141 
     | 
    
         
             
                  class SslClient
         
     | 
| 
         @@ -254,7 +158,7 @@ module Fluent 
     | 
|
| 
       254 
158 
     | 
    
         
             
                    # rubocop:enable Metrics/ParameterLists
         
     | 
| 
       255 
159 
     | 
    
         | 
| 
       256 
160 
     | 
    
         
             
                    def ssl_info
         
     | 
| 
       257 
     | 
    
         
            -
                      info = SslInfo.new(host: host, port: port)
         
     | 
| 
      
 161 
     | 
    
         
            +
                      info = Fluent::Plugin::SslCheck::SslInfo.new(host: host, port: port)
         
     | 
| 
       258 
162 
     | 
    
         
             
                      begin
         
     | 
| 
       259 
163 
     | 
    
         
             
                        Timeout.timeout(timeout) do
         
     | 
| 
       260 
164 
     | 
    
         
             
                          tcp_socket = TCPSocket.open(host, port)
         
     | 
| 
         @@ -275,18 +179,10 @@ module Fluent 
     | 
|
| 
       275 
179 
     | 
    
         
             
                      info
         
     | 
| 
       276 
180 
     | 
    
         
             
                    end
         
     | 
| 
       277 
181 
     | 
    
         | 
| 
       278 
     | 
    
         
            -
                    def store
         
     | 
| 
       279 
     | 
    
         
            -
                      OpenSSL::X509::Store.new.tap do |store|
         
     | 
| 
       280 
     | 
    
         
            -
                        store.set_default_paths
         
     | 
| 
       281 
     | 
    
         
            -
                        store.add_path(ca_path) if ca_path
         
     | 
| 
       282 
     | 
    
         
            -
                        store.add_file(ca_file) if ca_file
         
     | 
| 
       283 
     | 
    
         
            -
                      end
         
     | 
| 
       284 
     | 
    
         
            -
                    end
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
182 
     | 
    
         
             
                    def ssl_context
         
     | 
| 
       287 
183 
     | 
    
         
             
                      OpenSSL::SSL::SSLContext.new.tap do |ssl_context|
         
     | 
| 
       288 
184 
     | 
    
         
             
                        ssl_context.verify_mode = verify_mode
         
     | 
| 
       289 
     | 
    
         
            -
                        ssl_context.cert_store =  
     | 
| 
      
 185 
     | 
    
         
            +
                        ssl_context.cert_store = ssl_store(ca_path: ca_path, ca_file: ca_file)
         
     | 
| 
       290 
186 
     | 
    
         
             
                        ssl_context.min_version = nil
         
     | 
| 
       291 
187 
     | 
    
         
             
                        ssl_context.max_version = OpenSSL::SSL::TLS1_2_VERSION
         
     | 
| 
       292 
188 
     | 
    
         
             
                        ssl_context.cert = OpenSSL::X509::Certificate.new(File.open(cert)) if cert
         
     | 
| 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright 2024- Thomas Tych
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 7 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 8 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 13 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 14 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 15 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 16 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            require 'fluent/plugin/input'
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            require_relative 'extensions/time'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require_relative 'ssl_check'
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 26 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 27 
     | 
    
         
            +
                class SslFileCheckInput < Fluent::Plugin::Input
         
     | 
| 
      
 28 
     | 
    
         
            +
                  NAME = 'ssl_file_check'
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Fluent::Plugin.register_input(NAME, self)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  include Fluent::Plugin::SslCheck::SslInputEmit
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  DEFAULT_TAG = NAME
         
     | 
| 
      
 34 
     | 
    
         
            +
                  DEFAULT_INTERVAL = 600
         
     | 
| 
      
 35 
     | 
    
         
            +
                  DEFAULT_LOG_EVENTS = true
         
     | 
| 
      
 36 
     | 
    
         
            +
                  DEFAULT_METRIC_EVENTS = false
         
     | 
| 
      
 37 
     | 
    
         
            +
                  DEFAULT_EVENT_PREFIX = ''
         
     | 
| 
      
 38 
     | 
    
         
            +
                  DEFAULT_TIMESTAMP_FORMAT = :iso
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  desc 'Tag to emit events on'
         
     | 
| 
      
 41 
     | 
    
         
            +
                  config_param :tag, :string, default: DEFAULT_TAG
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  desc 'Paths of local certificate to check'
         
     | 
| 
      
 44 
     | 
    
         
            +
                  config_param :paths, :array, default: [], value_type: :string
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  desc 'Interval for the check execution'
         
     | 
| 
      
 47 
     | 
    
         
            +
                  config_param :interval, :time, default: DEFAULT_INTERVAL
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  desc 'CA path to load'
         
     | 
| 
      
 50 
     | 
    
         
            +
                  config_param :ca_path, :string, default: nil
         
     | 
| 
      
 51 
     | 
    
         
            +
                  desc 'CA file to load'
         
     | 
| 
      
 52 
     | 
    
         
            +
                  config_param :ca_file, :string, default: nil
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  desc 'Emit log events'
         
     | 
| 
      
 55 
     | 
    
         
            +
                  config_param :log_events, :bool, default: DEFAULT_LOG_EVENTS
         
     | 
| 
      
 56 
     | 
    
         
            +
                  desc 'Emit metric events'
         
     | 
| 
      
 57 
     | 
    
         
            +
                  config_param :metric_events, :bool, default: DEFAULT_METRIC_EVENTS
         
     | 
| 
      
 58 
     | 
    
         
            +
                  desc 'Event prefix'
         
     | 
| 
      
 59 
     | 
    
         
            +
                  config_param :event_prefix, :string, default: DEFAULT_EVENT_PREFIX
         
     | 
| 
      
 60 
     | 
    
         
            +
                  desc 'Timestamp format'
         
     | 
| 
      
 61 
     | 
    
         
            +
                  config_param :timestamp_format, :enum, list: %i[iso epochmillis], default: DEFAULT_TIMESTAMP_FORMAT
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  helpers :timer
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def configure(conf)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    super
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    raise Fluent::ConfigError, 'tag can not be empty.' if !tag || tag.empty?
         
     | 
| 
      
 70 
     | 
    
         
            +
                    raise Fluent::ConfigError, 'paths can not be empty.' unless paths
         
     | 
| 
      
 71 
     | 
    
         
            +
                    raise Fluent::ConfigError, 'interval can not be < 1.' if !interval || interval < 1
         
     | 
| 
      
 72 
     | 
    
         
            +
                    raise Fluent::ConfigError, 'ca_path should be a dir.' if ca_path && !File.directory?(ca_path)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    raise Fluent::ConfigError, 'ca_file should be a file.' if ca_file && !File.file?(ca_file)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    log.warn("#{NAME}: paths is empty, nothing to process") if paths.empty?
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def start
         
     | 
| 
      
 80 
     | 
    
         
            +
                    super
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    timer_execute(:ssl_file_check_timer, 1, repeat: false, &method(:check)) if interval > 60
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    timer_execute(:ssl_file_check_timer, interval, repeat: true, &method(:check))
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  # rubocop:disable Lint/SuppressedException
         
     | 
| 
      
 88 
     | 
    
         
            +
                  def check
         
     | 
| 
      
 89 
     | 
    
         
            +
                    paths.each do |cert_path|
         
     | 
| 
      
 90 
     | 
    
         
            +
                      ssl_info = fetch_ssl_info(cert_path)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      emit_logs(ssl_info) if log_events
         
     | 
| 
      
 92 
     | 
    
         
            +
                      emit_metrics(ssl_info) if metric_events
         
     | 
| 
      
 93 
     | 
    
         
            +
                    rescue StandardError
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  # rubocop:enable Lint/SuppressedException
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                  def fetch_ssl_info(filepath)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    ssl_file = Fluent::Plugin::SslCheck::FileChecker.new(filepath, ca_path: ca_path, ca_file: ca_file)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    ssl_file.ssl_info
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'ssl_common'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative 'ssl_info'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 10 
     | 
    
         
            +
                module SslCheck
         
     | 
| 
      
 11 
     | 
    
         
            +
                  class FileChecker
         
     | 
| 
      
 12 
     | 
    
         
            +
                    attr_reader :filepath, :ca_path, :ca_file
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    include Fluent::Plugin::SslCheck::SslCommon
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def initialize(filepath, ca_path: nil, ca_file: nil)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @filepath = filepath
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @ca_path = ca_path
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @ca_file = ca_file
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    def certificate
         
     | 
| 
      
 23 
     | 
    
         
            +
                      @certificate ||= OpenSSL::X509::Certificate.new(File.read(filepath_absolute))
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    def filepath_absolute
         
     | 
| 
      
 27 
     | 
    
         
            +
                      File.expand_path(filepath)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def ssl_info
         
     | 
| 
      
 31 
     | 
    
         
            +
                      info = Fluent::Plugin::SslCheck::SslInfo.new(host: hostname, path: filepath_absolute)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 33 
     | 
    
         
            +
                        ca_store = ssl_store(ca_path: ca_path, ca_file: ca_file)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        ca_store.verify(certificate)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                        info.cert = certificate
         
     | 
| 
      
 37 
     | 
    
         
            +
                        info.cert_chain = ca_store.chain
         
     | 
| 
      
 38 
     | 
    
         
            +
                        info.error = ca_store.error_string if ca_store.error != 0
         
     | 
| 
      
 39 
     | 
    
         
            +
                      rescue StandardError => e
         
     | 
| 
      
 40 
     | 
    
         
            +
                        info.error = e
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
                      info
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    def hostname
         
     | 
| 
      
 46 
     | 
    
         
            +
                      Socket.gethostname
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 7 
     | 
    
         
            +
                module SslCheck
         
     | 
| 
      
 8 
     | 
    
         
            +
                  module SslCommon
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def ssl_store(ca_path: nil, ca_file: nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      OpenSSL::X509::Store.new.tap do |store|
         
     | 
| 
      
 11 
     | 
    
         
            +
                        store.set_default_paths
         
     | 
| 
      
 12 
     | 
    
         
            +
                        store.add_path(ca_path) if ca_path
         
     | 
| 
      
 13 
     | 
    
         
            +
                        store.add_file(ca_file) if ca_file
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 7 
     | 
    
         
            +
                module SslCheck
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # ssl info
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #  to encapsulate extracted ssl information
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class SslInfo
         
     | 
| 
      
 11 
     | 
    
         
            +
                    OK = 1
         
     | 
| 
      
 12 
     | 
    
         
            +
                    KO = 0
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    attr_accessor :host, :port, :path, :cert, :cert_chain, :ssl_version, :error
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    # rubocop:disable Metrics/ParameterLists
         
     | 
| 
      
 17 
     | 
    
         
            +
                    def initialize(host: nil, port: nil, path: nil, cert: nil, cert_chain: nil, ssl_version: nil,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                   error: nil, time: nil)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @host = host
         
     | 
| 
      
 20 
     | 
    
         
            +
                      @port = port
         
     | 
| 
      
 21 
     | 
    
         
            +
                      @path = path
         
     | 
| 
      
 22 
     | 
    
         
            +
                      @cert = cert
         
     | 
| 
      
 23 
     | 
    
         
            +
                      @cert_chain = cert_chain
         
     | 
| 
      
 24 
     | 
    
         
            +
                      @ssl_version = ssl_version
         
     | 
| 
      
 25 
     | 
    
         
            +
                      @error = error
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @time = time
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # rubocop:enable Metrics/ParameterLists
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def subject_s
         
     | 
| 
      
 31 
     | 
    
         
            +
                      cert.subject.to_utf8 if cert&.subject
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def expire_in_days
         
     | 
| 
      
 35 
     | 
    
         
            +
                      return unless cert&.not_after
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      expire_in = cert.not_after
         
     | 
| 
      
 38 
     | 
    
         
            +
                      ((expire_in - time) / 3600 / 24).to_i
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    def not_after
         
     | 
| 
      
 42 
     | 
    
         
            +
                      return unless cert
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      cert.not_after.iso8601(3)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    def serial
         
     | 
| 
      
 48 
     | 
    
         
            +
                      cert&.serial&.to_s(16)&.downcase
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    def status
         
     | 
| 
      
 52 
     | 
    
         
            +
                      return KO if error
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                      OK
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    def time
         
     | 
| 
      
 58 
     | 
    
         
            +
                      @time ||= Time.now.utc
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    def time_utc
         
     | 
| 
      
 62 
     | 
    
         
            +
                      time.utc
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    def error_class
         
     | 
| 
      
 66 
     | 
    
         
            +
                      return unless error
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                      return error if error.is_a?(String)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                      error.class.to_s
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 5 
     | 
    
         
            +
                module SslCheck
         
     | 
| 
      
 6 
     | 
    
         
            +
                  module SslInputEmit
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def emit_logs(ssl_info)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      record = {
         
     | 
| 
      
 9 
     | 
    
         
            +
                        'timestamp' => ssl_info.time_utc.send("to_#{timestamp_format}"),
         
     | 
| 
      
 10 
     | 
    
         
            +
                        'status' => ssl_info.status,
         
     | 
| 
      
 11 
     | 
    
         
            +
                        'host' => ssl_info.host,
         
     | 
| 
      
 12 
     | 
    
         
            +
                        'port' => ssl_info.port,
         
     | 
| 
      
 13 
     | 
    
         
            +
                        'path' => ssl_info.path,
         
     | 
| 
      
 14 
     | 
    
         
            +
                        'ssl_version' => ssl_info.ssl_version,
         
     | 
| 
      
 15 
     | 
    
         
            +
                        'ssl_dn' => ssl_info.subject_s,
         
     | 
| 
      
 16 
     | 
    
         
            +
                        'ssl_not_after' => ssl_info.not_after,
         
     | 
| 
      
 17 
     | 
    
         
            +
                        'expire_in_days' => ssl_info.expire_in_days,
         
     | 
| 
      
 18 
     | 
    
         
            +
                        'serial' => ssl_info.serial
         
     | 
| 
      
 19 
     | 
    
         
            +
                      }
         
     | 
| 
      
 20 
     | 
    
         
            +
                      record.update('error_class' => ssl_info.error_class) if ssl_info.error_class
         
     | 
| 
      
 21 
     | 
    
         
            +
                      router.emit(tag, Fluent::EventTime.from_time(ssl_info.time_utc), record)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    def emit_metrics(ssl_info)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      emit_metric_status(ssl_info)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      emit_metric_expirency(ssl_info)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def emit_metric_status(ssl_info)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      record = {
         
     | 
| 
      
 31 
     | 
    
         
            +
                        'timestamp' => ssl_info.time_utc.send("to_#{timestamp_format}"),
         
     | 
| 
      
 32 
     | 
    
         
            +
                        'metric_name' => 'ssl_status',
         
     | 
| 
      
 33 
     | 
    
         
            +
                        'metric_value' => ssl_info.status,
         
     | 
| 
      
 34 
     | 
    
         
            +
                        "#{event_prefix}host" => ssl_info.host,
         
     | 
| 
      
 35 
     | 
    
         
            +
                        "#{event_prefix}port" => ssl_info.port,
         
     | 
| 
      
 36 
     | 
    
         
            +
                        "#{event_prefix}path" => ssl_info.path,
         
     | 
| 
      
 37 
     | 
    
         
            +
                        "#{event_prefix}ssl_dn" => ssl_info.subject_s,
         
     | 
| 
      
 38 
     | 
    
         
            +
                        "#{event_prefix}ssl_version" => ssl_info.ssl_version,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        "#{event_prefix}ssl_not_after" => ssl_info.not_after,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        "#{event_prefix}serial" => ssl_info.serial
         
     | 
| 
      
 41 
     | 
    
         
            +
                      }
         
     | 
| 
      
 42 
     | 
    
         
            +
                      router.emit(tag, Fluent::EventTime.from_time(ssl_info.time_utc), record)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    def emit_metric_expirency(ssl_info)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      return unless ssl_info.cert
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                      record = {
         
     | 
| 
      
 49 
     | 
    
         
            +
                        'timestamp' => ssl_info.time_utc.send("to_#{timestamp_format}"),
         
     | 
| 
      
 50 
     | 
    
         
            +
                        'metric_name' => 'ssl_expirency',
         
     | 
| 
      
 51 
     | 
    
         
            +
                        'metric_value' => ssl_info.expire_in_days,
         
     | 
| 
      
 52 
     | 
    
         
            +
                        "#{event_prefix}host" => ssl_info.host,
         
     | 
| 
      
 53 
     | 
    
         
            +
                        "#{event_prefix}port" => ssl_info.port,
         
     | 
| 
      
 54 
     | 
    
         
            +
                        "#{event_prefix}path" => ssl_info.path,
         
     | 
| 
      
 55 
     | 
    
         
            +
                        "#{event_prefix}ssl_dn" => ssl_info.subject_s,
         
     | 
| 
      
 56 
     | 
    
         
            +
                        "#{event_prefix}serial" => ssl_info.serial
         
     | 
| 
      
 57 
     | 
    
         
            +
                      }
         
     | 
| 
      
 58 
     | 
    
         
            +
                      router.emit(tag, Fluent::EventTime.from_time(ssl_info.time_utc), record)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'ssl_check/ssl_input_emit'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'ssl_check/ssl_common'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'ssl_check/ssl_info'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative 'ssl_check/file_checker'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Fluent
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Plugin
         
     | 
| 
      
 10 
     | 
    
         
            +
                module SslCheck
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: fluent-plugin-ssl-check
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.4.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Thomas Tych
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2024-12-06 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: bump
         
     | 
| 
         @@ -58,6 +58,26 @@ dependencies: 
     | 
|
| 
       58 
58 
     | 
    
         
             
                - - ">="
         
     | 
| 
       59 
59 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       60 
60 
     | 
    
         
             
                    version: 11.1.3
         
     | 
| 
      
 61 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 62 
     | 
    
         
            +
              name: mocha
         
     | 
| 
      
 63 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 64 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 65 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 66 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 67 
     | 
    
         
            +
                    version: '2.6'
         
     | 
| 
      
 68 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 69 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 70 
     | 
    
         
            +
                    version: 2.6.1
         
     | 
| 
      
 71 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 72 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 73 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 74 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 75 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 77 
     | 
    
         
            +
                    version: '2.6'
         
     | 
| 
      
 78 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 79 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 80 
     | 
    
         
            +
                    version: 2.6.1
         
     | 
| 
       61 
81 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       62 
82 
     | 
    
         
             
              name: rake
         
     | 
| 
       63 
83 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -188,6 +208,7 @@ extensions: [] 
     | 
|
| 
       188 
208 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       189 
209 
     | 
    
         
             
            files:
         
     | 
| 
       190 
210 
     | 
    
         
             
            - ".gitignore"
         
     | 
| 
      
 211 
     | 
    
         
            +
            - ".gitlab-ci.yml"
         
     | 
| 
       191 
212 
     | 
    
         
             
            - ".rubocop.yml"
         
     | 
| 
       192 
213 
     | 
    
         
             
            - ".ruby-version"
         
     | 
| 
       193 
214 
     | 
    
         
             
            - Gemfile
         
     | 
| 
         @@ -198,6 +219,12 @@ files: 
     | 
|
| 
       198 
219 
     | 
    
         
             
            - fluent-plugin-ssl-check.gemspec
         
     | 
| 
       199 
220 
     | 
    
         
             
            - lib/fluent/plugin/extensions/time.rb
         
     | 
| 
       200 
221 
     | 
    
         
             
            - lib/fluent/plugin/in_ssl_check.rb
         
     | 
| 
      
 222 
     | 
    
         
            +
            - lib/fluent/plugin/in_ssl_file_check.rb
         
     | 
| 
      
 223 
     | 
    
         
            +
            - lib/fluent/plugin/ssl_check.rb
         
     | 
| 
      
 224 
     | 
    
         
            +
            - lib/fluent/plugin/ssl_check/file_checker.rb
         
     | 
| 
      
 225 
     | 
    
         
            +
            - lib/fluent/plugin/ssl_check/ssl_common.rb
         
     | 
| 
      
 226 
     | 
    
         
            +
            - lib/fluent/plugin/ssl_check/ssl_info.rb
         
     | 
| 
      
 227 
     | 
    
         
            +
            - lib/fluent/plugin/ssl_check/ssl_input_emit.rb
         
     | 
| 
       201 
228 
     | 
    
         
             
            homepage: https://gitlab.com/ttych/fluent-plugin-ssl-check
         
     | 
| 
       202 
229 
     | 
    
         
             
            licenses:
         
     | 
| 
       203 
230 
     | 
    
         
             
            - Apache-2.0
         
     | 
| 
         @@ -218,7 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       218 
245 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       219 
246 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       220 
247 
     | 
    
         
             
            requirements: []
         
     | 
| 
       221 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
      
 248 
     | 
    
         
            +
            rubygems_version: 3.5.22
         
     | 
| 
       222 
249 
     | 
    
         
             
            signing_key:
         
     | 
| 
       223 
250 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       224 
251 
     | 
    
         
             
            summary: fluentd plugin to check ssl endpoint
         
     |