|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# |
| 4 | +# Copyright (C) 2025 Nethesis S.r.l. |
| 5 | +# SPDX-License-Identifier: GPL-3.0-or-later |
| 6 | +# |
| 7 | + |
| 8 | +import os |
| 9 | +import json |
| 10 | +import sys |
| 11 | +import subprocess |
| 12 | + |
| 13 | +def main(): |
| 14 | + facts = {} |
| 15 | + facts.update(get_addresses_facts()) |
| 16 | + facts.update(get_filter_facts()) |
| 17 | + facts.update(get_bypass_rules_facts()) |
| 18 | + facts.update(get_mailboxes_facts()) |
| 19 | + facts.update(get_public_mailboxes_facts()) |
| 20 | + facts.update(get_domains_facts()) |
| 21 | + facts.update(get_relay_rules_facts()) |
| 22 | + facts.update(get_relay_settings_facts()) |
| 23 | + facts.update(get_always_bcc_facts()) |
| 24 | + facts.update(get_configuration_facts()) |
| 25 | + facts.update(get_mailbox_settings_facts()) |
| 26 | + facts.update(get_master_users_facts()) |
| 27 | + facts.update(get_queue_settings_facts()) |
| 28 | + json.dump(facts, sys.stdout) |
| 29 | + |
| 30 | +def get_addresses_facts(): |
| 31 | + with subprocess.Popen(["../actions/list-addresses/10list_addresses"], stdout=subprocess.PIPE) as proc: |
| 32 | + try: |
| 33 | + odata = json.load(proc.stdout) |
| 34 | + except json.JSONDecodeError: |
| 35 | + return {"get_addresses_facts_error": True} |
| 36 | + oaddresses = odata['addresses'] |
| 37 | + facts = { |
| 38 | + "addresses_total_count": len(oaddresses), |
| 39 | + "adduser_domains_count": len(odata['adduser_domains']), |
| 40 | + "addgroup_domains_count": len(odata['addgroup_domains']), |
| 41 | + } |
| 42 | + atype_count_dict = dict() |
| 43 | + dtype_count_dict = dict() |
| 44 | + for adx in oaddresses: |
| 45 | + akey = f'addresses_{adx["atype"]}_count' |
| 46 | + atype_count_dict.setdefault(akey, 0) |
| 47 | + atype_count_dict[akey] += 1 |
| 48 | + for ddx in adx.get('destinations', []): |
| 49 | + dkey = f'destinations_{ddx["dtype"]}_count' |
| 50 | + dtype_count_dict.setdefault(dkey, 0) |
| 51 | + dtype_count_dict[dkey] += 1 |
| 52 | + facts.update(atype_count_dict) |
| 53 | + facts.update(dtype_count_dict) |
| 54 | + return facts |
| 55 | + |
| 56 | +def get_filter_facts(): |
| 57 | + with subprocess.Popen(["../actions/get-filter-configuration/10get_filter_configuration"], stdout=subprocess.PIPE) as proc: |
| 58 | + try: |
| 59 | + odata = json.load(proc.stdout) |
| 60 | + except json.JSONDecodeError: |
| 61 | + return {"get_filter_facts_error": True} |
| 62 | + try: |
| 63 | + del odata["antispam"]["rspamd_url"] # remove sensitive information |
| 64 | + del odata["bypass_rules"] # duplicate |
| 65 | + except: |
| 66 | + pass |
| 67 | + return {"filter": odata} |
| 68 | + |
| 69 | +def get_bypass_rules_facts(): |
| 70 | + with subprocess.Popen(["../actions/list-bypass-rules/10list_bypass_rules"], stdout=subprocess.PIPE) as proc: |
| 71 | + try: |
| 72 | + odata = json.load(proc.stdout)["bypass_rules"] |
| 73 | + except json.JSONDecodeError: |
| 74 | + return {"get_bypass_rules_facts_error": True} |
| 75 | + facts = {"bypass_rules_count": len(odata)} |
| 76 | + for orule in odata: |
| 77 | + bkey = f'bypass_{orule["direction"]}_{orule["type"]}_count' |
| 78 | + facts.setdefault(bkey, 0) |
| 79 | + facts[bkey] += 1 |
| 80 | + return facts |
| 81 | + |
| 82 | +def get_mailboxes_facts(): |
| 83 | + with subprocess.Popen(["../actions/list-user-mailboxes/10list_user_mailboxes"], stdout=subprocess.PIPE) as proc: |
| 84 | + try: |
| 85 | + odata = json.load(proc.stdout)["user_mailboxes"] |
| 86 | + except json.JSONDecodeError: |
| 87 | + return {"get_mailboxes_facts_error": True} |
| 88 | + |
| 89 | + disabled_users = os.getenv("DOVECOT_DISABLED_USERS", "") |
| 90 | + |
| 91 | + facts = { |
| 92 | + "mailboxes_total_count": len(odata), |
| 93 | + "mailboxes_custom_spam_retention_count": 0, |
| 94 | + "mailboxes_custom_quota_count": 0, |
| 95 | + "mailboxes_forward_total_count": 0, |
| 96 | + "mailboxes_forward_keepcopy_count": 0, |
| 97 | + "mailboxes_disabled_count": len(disabled_users.split(",")) if disabled_users else 0, |
| 98 | + } |
| 99 | + for mbx in odata: |
| 100 | + if mbx.get('quota', {}).get('custom'): |
| 101 | + facts['mailboxes_custom_quota_count'] += 1 |
| 102 | + if mbx.get('spam_retention', {}).get('custom'): |
| 103 | + facts['mailboxes_custom_spam_retention_count'] += 1 |
| 104 | + if mbx.get('forward'): |
| 105 | + facts['mailboxes_forward_total_count'] += 1 |
| 106 | + if mbx['forward'].get('keepcopy'): |
| 107 | + facts['mailboxes_forward_keepcopy_count'] += 1 |
| 108 | + for fwx in mbx['forward']['destinations']: |
| 109 | + fkey = f'mailboxes_forward_{fwx["dtype"]}_count' |
| 110 | + facts.setdefault(fkey, 0) |
| 111 | + facts[fkey] += 1 |
| 112 | + return facts |
| 113 | + |
| 114 | +def get_public_mailboxes_facts(): |
| 115 | + with subprocess.Popen(["../actions/list-public-mailboxes/10list_public_mailboxes"], stdout=subprocess.PIPE) as proc: |
| 116 | + try: |
| 117 | + odata = json.load(proc.stdout) |
| 118 | + except json.JSONDecodeError: |
| 119 | + return {"get_public_mailboxes_facts_error": True} |
| 120 | + |
| 121 | + facts = { |
| 122 | + "public_mailboxes_total_count": len(odata), |
| 123 | + } |
| 124 | + return facts |
| 125 | + |
| 126 | +def get_domains_facts(): |
| 127 | + with subprocess.Popen(["../actions/list-domains/10list_domains"], stdout=subprocess.PIPE) as proc: |
| 128 | + try: |
| 129 | + odata = json.load(proc.stdout) |
| 130 | + except json.JSONDecodeError: |
| 131 | + return {"get_domains_facts_error": True} |
| 132 | + |
| 133 | + facts = { |
| 134 | + "domains_total_count": len(odata), |
| 135 | + "domains_description_count": 0, |
| 136 | + } |
| 137 | + |
| 138 | + for odomain in odata: |
| 139 | + if odomain.get("description"): |
| 140 | + facts["domains_description_count"] += 1 |
| 141 | + if odomain.get("catchall"): |
| 142 | + ckey = f'domains_catchall_{odomain["catchall"]["dtype"]}_count' |
| 143 | + facts.setdefault(ckey, 0) |
| 144 | + facts[ckey] += 1 |
| 145 | + |
| 146 | + return facts |
| 147 | + |
| 148 | +def get_relay_rules_facts(): |
| 149 | + with subprocess.Popen(["../actions/list-relay-rules/10list_relays"], stdout=subprocess.PIPE) as proc: |
| 150 | + try: |
| 151 | + odata = json.load(proc.stdout)["rules"] |
| 152 | + except json.JSONDecodeError: |
| 153 | + return {"get_relay_rules_facts_error": True} |
| 154 | + |
| 155 | + facts = { |
| 156 | + "relay_rules_total_count": len(odata), |
| 157 | + "relay_rules_tls_count": 0, |
| 158 | + "relay_rules_has_password_count": 0, |
| 159 | + "relay_rules_enabled_count": 0, |
| 160 | + } |
| 161 | + |
| 162 | + for orule in odata: |
| 163 | + tkey = f'relay_rules_{orule["rule_type"]}_count' |
| 164 | + facts.setdefault(tkey, 0) |
| 165 | + facts[tkey] += 1 |
| 166 | + if orule.get('tls'): |
| 167 | + facts['relay_rules_tls_count'] += 1 |
| 168 | + if orule.get('has_password'): |
| 169 | + facts['relay_rules_has_password_count'] += 1 |
| 170 | + if orule.get('enabled'): |
| 171 | + facts['relay_rules_enabled_count'] += 1 |
| 172 | + |
| 173 | + return facts |
| 174 | + |
| 175 | +def get_relay_settings_facts(): |
| 176 | + with subprocess.Popen(["../actions/get-relay-configuration/10get_relay_settings"], stdout=subprocess.PIPE) as proc: |
| 177 | + try: |
| 178 | + odata = json.load(proc.stdout) |
| 179 | + except json.JSONDecodeError: |
| 180 | + return {"get_relay_settings_facts_error": True} |
| 181 | + |
| 182 | + return { |
| 183 | + "relay_settings_postfix_restricted_sender_enabled": odata.get("postfix_restricted_sender"), |
| 184 | + "relay_settings_networks_count": len(odata.get("networks", [])), |
| 185 | + } |
| 186 | + |
| 187 | +def get_always_bcc_facts(): |
| 188 | + with subprocess.Popen(["../actions/get-always-bcc/20read"], stdout=subprocess.PIPE) as proc: |
| 189 | + try: |
| 190 | + odata = json.load(proc.stdout) |
| 191 | + except json.JSONDecodeError: |
| 192 | + return {"get_always_bcc_facts_error": True} |
| 193 | + |
| 194 | + return { |
| 195 | + "always_bcc_enabled": bool(odata.get("bcc")), |
| 196 | + } |
| 197 | + |
| 198 | +def get_configuration_facts(): |
| 199 | + with subprocess.Popen(["../actions/get-configuration/20read"], stdout=subprocess.PIPE) as proc: |
| 200 | + try: |
| 201 | + odata = json.load(proc.stdout) |
| 202 | + except json.JSONDecodeError: |
| 203 | + return {"get_configuration_facts_error": True} |
| 204 | + |
| 205 | + return { |
| 206 | + "configuration_user_domain_schema": odata.get("user_domain", {}).get("schema"), |
| 207 | + } |
| 208 | + |
| 209 | +def get_mailbox_settings_facts(): |
| 210 | + with subprocess.Popen(["../actions/get-mailbox-settings/10get_mailbox_settings"], stdout=subprocess.PIPE) as proc: |
| 211 | + try: |
| 212 | + odata = json.load(proc.stdout) |
| 213 | + except json.JSONDecodeError: |
| 214 | + return {"get_mailbox_settings_facts_error": True} |
| 215 | + |
| 216 | + return { |
| 217 | + "mailbox_settings_spam_prefix_enabled": bool(odata.get("spam_prefix", {}).get("enabled")), |
| 218 | + "mailbox_settings_sharedseen_enabled": bool(odata.get("sharedseen", {}).get("enabled")), |
| 219 | + "mailbox_settings_spam_folder_enabled": bool(odata.get("spam_folder", {}).get("enabled")), |
| 220 | + "mailbox_settings_spam_retention_value": odata.get("spam_retention", {}).get("value"), |
| 221 | + "mailbox_settings_quota_enabled": bool(odata.get("quota", {}).get("limit")), |
| 222 | + } |
| 223 | + |
| 224 | +def get_queue_settings_facts(): |
| 225 | + with subprocess.Popen(["../actions/get-queue-settings/10get_queue_settings"], stdout=subprocess.PIPE) as proc: |
| 226 | + try: |
| 227 | + odata = json.load(proc.stdout) |
| 228 | + except json.JSONDecodeError: |
| 229 | + return {"get_queue_settings_facts_error": True} |
| 230 | + |
| 231 | + return { |
| 232 | + "queue_settings_maximal_queue_lifetime": odata.get("maximal_queue_lifetime"), |
| 233 | + } |
| 234 | + |
| 235 | +def get_master_users_facts(): |
| 236 | + with subprocess.Popen(["../actions/get-master-users/10get_master_users"], stdout=subprocess.PIPE) as proc: |
| 237 | + try: |
| 238 | + odata = json.load(proc.stdout) |
| 239 | + except json.JSONDecodeError: |
| 240 | + return {"get_master_users_facts_error": True} |
| 241 | + |
| 242 | + return { |
| 243 | + "master_users_count": len(odata.get("master_users", [])), |
| 244 | + } |
| 245 | + |
| 246 | + |
| 247 | +if __name__ == "__main__": |
| 248 | + main() |
0 commit comments