1## This Source Code Form is subject to the terms of the Mozilla Public 2## License, v. 2.0. If a copy of the MPL was not distributed with this 3## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4## 5## Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved. 6 7defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckCertificateExpirationCommand do 8 alias RabbitMQ.CLI.Core.DocGuide 9 alias RabbitMQ.CLI.TimeUnit, as: TU 10 @behaviour RabbitMQ.CLI.CommandBehaviour 11 12 import RabbitMQ.CLI.Core.Listeners 13 14 def switches(), do: [unit: :string, within: :integer] 15 16 def merge_defaults(args, opts) do 17 {args, Map.merge(%{unit: "weeks", within: 4}, opts)} 18 end 19 20 def validate(args, _) when length(args) > 0 do 21 {:validation_failure, :too_many_args} 22 end 23 def validate(_, %{unit: unit}) do 24 case TU.known_unit?(unit) do 25 true -> 26 :ok 27 28 false -> 29 {:validation_failure, "unit '#{unit}' is not supported. Please use one of: days, weeks, months, years"} 30 end 31 end 32 def validate(_, _), do: :ok 33 34 def run([], %{node: node_name, unit: unit, within: within, timeout: timeout}) do 35 case :rabbit_misc.rpc_call(node_name, :rabbit_networking, :active_listeners, [], timeout) do 36 {:error, _} = err -> 37 err 38 39 {:error, _, _} = err -> 40 err 41 42 {:badrpc, _} = err -> 43 err 44 45 xs when is_list(xs) -> 46 listeners = listeners_on(xs, node_name) 47 seconds = TU.convert(within, unit) 48 Enum.reduce(listeners, [], fn (listener, acc) -> case listener_expiring_within(listener, seconds) do 49 false -> acc 50 expiring -> [expiring | acc] 51 end 52 end) 53 end 54 end 55 56 def output([], %{formatter: "json"}) do 57 {:ok, %{"result" => "ok"}} 58 end 59 60 def output([], %{unit: unit, within: within}) do 61 unit_label = unit_label(within, unit) 62 {:ok, "No certificates are expiring within #{within} #{unit_label}."} 63 end 64 65 def output(listeners, %{formatter: "json"}) do 66 {:error, :check_failed, %{"result" => "error", "expired" => Enum.map(listeners, &expired_listener_map/1)}} 67 end 68 69 def output(listeners, %{}) do 70 {:error, :check_failed, Enum.map(listeners, &expired_listener_map/1)} 71 end 72 73 def unit_label(1, unit) do 74 unit |> String.slice(0..-2) 75 end 76 def unit_label(_within, unit) do 77 unit 78 end 79 80 def usage, do: "check_certificate_expiration [--within <period>] [--unit <unit>]" 81 82 def usage_additional() do 83 [ 84 ["<period>", "period of time to check. Default is four (weeks)."], 85 ["<unit>", "time unit for the period, can be days, weeks, months, years. Default is weeks."], 86 ] 87 end 88 89 def usage_doc_guides() do 90 [ 91 DocGuide.tls(), 92 DocGuide.networking() 93 ] 94 end 95 96 def help_section(), do: :observability_and_health_checks 97 98 def description(), do: "Checks the expiration date on the certificates for every listener configured to use TLS" 99 100 def banner(_, %{node: node_name}), do: "Checking certificate expiration on node #{node_name} ..." 101end 102