From 3a5d4d5e86c59185c9a328ffc4ca1b6518af19a4 Mon Sep 17 00:00:00 2001 From: inexcode Date: Sat, 20 Aug 2022 22:49:51 +0400 Subject: [PATCH] Implement DNS records getter --- selfprivacy_api/graphql/queries/system.py | 19 +++++- selfprivacy_api/services/__init__.py | 45 +++++++++++-- .../services/bitwarden/__init__.py | 10 ++- selfprivacy_api/services/gitea/__init__.py | 10 ++- .../services/mailserver/__init__.py | 65 +++++++++++++------ .../services/nextcloud/__init__.py | 10 ++- selfprivacy_api/services/ocserv/__init__.py | 17 ++++- selfprivacy_api/services/pleroma/__init__.py | 10 ++- selfprivacy_api/utils/auth.py | 2 +- 9 files changed, 148 insertions(+), 40 deletions(-) diff --git a/selfprivacy_api/graphql/queries/system.py b/selfprivacy_api/graphql/queries/system.py index ef1476a..e3f0eff 100644 --- a/selfprivacy_api/graphql/queries/system.py +++ b/selfprivacy_api/graphql/queries/system.py @@ -9,6 +9,7 @@ from selfprivacy_api.graphql.queries.common import Alert, Severity from selfprivacy_api.graphql.queries.providers import DnsProvider, ServerProvider from selfprivacy_api.jobs import Jobs from selfprivacy_api.jobs.migrate_to_binds import is_bind_migrated +from selfprivacy_api.services import get_all_required_dns_records from selfprivacy_api.utils import ReadUserData import selfprivacy_api.actions.system as system_actions import selfprivacy_api.actions.ssh as ssh_actions @@ -21,7 +22,20 @@ class SystemDomainInfo: domain: str hostname: str provider: DnsProvider - required_dns_records: typing.List[DnsRecord] + @strawberry.field + def required_dns_records(self) -> typing.List[DnsRecord]: + """Collect all required DNS records for all services""" + return [ + DnsRecord( + record_type=record.type, + name=record.name, + content=record.content, + ttl=record.ttl, + priority=record.priority, + ) + for record in get_all_required_dns_records() + ] + def get_system_domain_info() -> SystemDomainInfo: @@ -31,8 +45,6 @@ def get_system_domain_info() -> SystemDomainInfo: domain=user_data["domain"], hostname=user_data["hostname"], provider=DnsProvider.CLOUDFLARE, - # TODO: get ip somehow - required_dns_records=[], ) @@ -142,6 +154,7 @@ class System: settings: SystemSettings = SystemSettings() info: SystemInfo = SystemInfo() provider: SystemProviderInfo = strawberry.field(resolver=get_system_provider_info) + @strawberry.field def busy(self) -> bool: """Check if the system is busy""" diff --git a/selfprivacy_api/services/__init__.py b/selfprivacy_api/services/__init__.py index eb9b7be..04d496f 100644 --- a/selfprivacy_api/services/__init__.py +++ b/selfprivacy_api/services/__init__.py @@ -7,8 +7,8 @@ from selfprivacy_api.services.mailserver import MailServer from selfprivacy_api.services.nextcloud import Nextcloud from selfprivacy_api.services.pleroma import Pleroma from selfprivacy_api.services.ocserv import Ocserv -from selfprivacy_api.services.service import Service - +from selfprivacy_api.services.service import Service, ServiceDnsRecord +import selfprivacy_api.utils.network as network_utils services: list[Service] = [ Bitwarden(), @@ -20,7 +20,7 @@ services: list[Service] = [ ] -def get_all_services() -> typing.List[Service]: +def get_all_services() -> list[Service]: return services @@ -31,13 +31,46 @@ def get_service_by_id(service_id: str) -> typing.Optional[Service]: return None -def get_enabled_services() -> typing.List[Service]: +def get_enabled_services() -> list[Service]: return [service for service in services if service.is_enabled()] -def get_disabled_services() -> typing.List[Service]: +def get_disabled_services() -> list[Service]: return [service for service in services if not service.is_enabled()] -def get_services_by_location(location: str) -> typing.List[Service]: +def get_services_by_location(location: str) -> list[Service]: return [service for service in services if service.get_location() == location] + +def get_all_required_dns_records() -> list[ServiceDnsRecord]: + ip4 = network_utils.get_ip4() + ip6 = network_utils.get_ip6() + dns_records: list[ServiceDnsRecord] = [ + ServiceDnsRecord( + type="A", + name="api", + content=ip4, + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="api", + content=ip6, + ttl=3600, + ), + ServiceDnsRecord( + type="A", + name="meet", + content=ip4, + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="meet", + content=ip6, + ttl=3600, + ), + ] + for service in get_enabled_services(): + dns_records += service.get_dns_records() + return dns_records diff --git a/selfprivacy_api/services/bitwarden/__init__.py b/selfprivacy_api/services/bitwarden/__init__.py index a581ec9..ea93de1 100644 --- a/selfprivacy_api/services/bitwarden/__init__.py +++ b/selfprivacy_api/services/bitwarden/__init__.py @@ -11,7 +11,7 @@ from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceS from selfprivacy_api.utils import ReadUserData, WriteUserData, get_domain from selfprivacy_api.utils.block_devices import BlockDevice from selfprivacy_api.utils.huey import huey -from selfprivacy_api.utils.network import get_ip4 +import selfprivacy_api.utils.network as network_utils from selfprivacy_api.services.bitwarden.icon import BITWARDEN_ICON @@ -132,7 +132,13 @@ class Bitwarden(Service): ServiceDnsRecord( type="A", name="password", - content=get_ip4(), + content=network_utils.get_ip4(), + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="password", + content=network_utils.get_ip6(), ttl=3600, ), ] diff --git a/selfprivacy_api/services/gitea/__init__.py b/selfprivacy_api/services/gitea/__init__.py index 7a5db1b..d563164 100644 --- a/selfprivacy_api/services/gitea/__init__.py +++ b/selfprivacy_api/services/gitea/__init__.py @@ -11,7 +11,7 @@ from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceS from selfprivacy_api.utils import ReadUserData, WriteUserData, get_domain from selfprivacy_api.utils.block_devices import BlockDevice from selfprivacy_api.utils.huey import huey -from selfprivacy_api.utils.network import get_ip4 +import selfprivacy_api.utils.network as network_utils from selfprivacy_api.services.gitea.icon import GITEA_ICON @@ -129,7 +129,13 @@ class Gitea(Service): ServiceDnsRecord( type="A", name="git", - content=get_ip4(), + content=network_utils.get_ip4(), + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="git", + content=network_utils.get_ip6(), ttl=3600, ), ] diff --git a/selfprivacy_api/services/mailserver/__init__.py b/selfprivacy_api/services/mailserver/__init__.py index dfcaa7f..ea085ba 100644 --- a/selfprivacy_api/services/mailserver/__init__.py +++ b/selfprivacy_api/services/mailserver/__init__.py @@ -9,11 +9,10 @@ from selfprivacy_api.services.generic_service_mover import FolderMoveNames, move from selfprivacy_api.services.generic_size_counter import get_storage_usage from selfprivacy_api.services.generic_status_getter import get_service_status from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceStatus -from selfprivacy_api.utils import ReadUserData, WriteUserData, get_dkim_key, get_domain -from selfprivacy_api.utils import huey +import selfprivacy_api.utils as utils from selfprivacy_api.utils.block_devices import BlockDevice from selfprivacy_api.utils.huey import huey -from selfprivacy_api.utils.network import get_ip4 +import selfprivacy_api.utils.network as network_utils from selfprivacy_api.services.mailserver.icon import MAILSERVER_ICON @@ -58,21 +57,34 @@ class MailServer(Service): imap_status = get_service_status("dovecot2.service") smtp_status = get_service_status("postfix.service") - if ( - imap_status == ServiceStatus.RUNNING - and smtp_status == ServiceStatus.RUNNING - ): - return ServiceStatus.RUNNING - elif imap_status == ServiceStatus.ERROR or smtp_status == ServiceStatus.ERROR: - return ServiceStatus.ERROR + if imap_status == ServiceStatus.ACTIVE and smtp_status == ServiceStatus.ACTIVE: + return ServiceStatus.ACTIVE + elif imap_status == ServiceStatus.FAILED or smtp_status == ServiceStatus.FAILED: + return ServiceStatus.FAILED elif ( - imap_status == ServiceStatus.STOPPED or smtp_status == ServiceStatus.STOPPED + imap_status == ServiceStatus.RELOADING + or smtp_status == ServiceStatus.RELOADING ): - return ServiceStatus.STOPPED + return ServiceStatus.RELOADING + elif ( + imap_status == ServiceStatus.ACTIVATING + or smtp_status == ServiceStatus.ACTIVATING + ): + return ServiceStatus.ACTIVATING + elif ( + imap_status == ServiceStatus.DEACTIVATING + or smtp_status == ServiceStatus.DEACTIVATING + ): + return ServiceStatus.DEACTIVATING + elif ( + imap_status == ServiceStatus.INACTIVE + or smtp_status == ServiceStatus.INACTIVE + ): + return ServiceStatus.INACTIVE elif imap_status == ServiceStatus.OFF or smtp_status == ServiceStatus.OFF: return ServiceStatus.OFF else: - return ServiceStatus.DEGRADED + return ServiceStatus.FAILED @staticmethod def enable(): @@ -115,7 +127,7 @@ class MailServer(Service): @staticmethod def get_location() -> str: - with ReadUserData() as user_data: + with utils.ReadUserData() as user_data: if user_data.get("useBinds", False): return user_data.get("mailserver", {}).get("location", "sda1") else: @@ -123,25 +135,38 @@ class MailServer(Service): @staticmethod def get_dns_records() -> typing.List[ServiceDnsRecord]: - domain = get_domain() - dkim_record = get_dkim_key(domain) - ip4 = get_ip4() + domain = utils.get_domain() + dkim_record = utils.get_dkim_key(domain) + ip4 = network_utils.get_ip4() + ip6 = network_utils.get_ip6() if dkim_record is None: return [] return [ + ServiceDnsRecord( + type="A", + name=domain, + content=ip4, + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name=domain, + content=ip6, + ttl=3600, + ), ServiceDnsRecord( type="MX", name=domain, content=domain, ttl=3600, priority=10 ), ServiceDnsRecord( - type="TXT", name="_dmarc", content=f"v=DMARC1; p=none", ttl=3600 + type="TXT", name="_dmarc", content=f"v=DMARC1; p=none", ttl=18000 ), ServiceDnsRecord( - type="TXT", name=domain, content=f"v=spf1 a mx ip4:{ip4} -all", ttl=3600 + type="TXT", name=domain, content=f"v=spf1 a mx ip4:{ip4} -all", ttl=18000 ), ServiceDnsRecord( - type="TXT", name="selector._domainkey", content=dkim_record, ttl=3600 + type="TXT", name="selector._domainkey", content=dkim_record, ttl=18000 ), ] diff --git a/selfprivacy_api/services/nextcloud/__init__.py b/selfprivacy_api/services/nextcloud/__init__.py index 6bd616a..4057b49 100644 --- a/selfprivacy_api/services/nextcloud/__init__.py +++ b/selfprivacy_api/services/nextcloud/__init__.py @@ -9,7 +9,7 @@ from selfprivacy_api.services.generic_status_getter import get_service_status from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceStatus from selfprivacy_api.utils import ReadUserData, WriteUserData, get_domain from selfprivacy_api.utils.block_devices import BlockDevice -from selfprivacy_api.utils.network import get_ip4 +import selfprivacy_api.utils.network as network_utils from selfprivacy_api.services.nextcloud.icon import NEXTCLOUD_ICON @@ -137,7 +137,13 @@ class Nextcloud(Service): ServiceDnsRecord( type="A", name="cloud", - content=get_ip4(), + content=network_utils.get_ip4(), + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="cloud", + content=network_utils.get_ip6(), ttl=3600, ), ] diff --git a/selfprivacy_api/services/ocserv/__init__.py b/selfprivacy_api/services/ocserv/__init__.py index 2c86259..dcfacaa 100644 --- a/selfprivacy_api/services/ocserv/__init__.py +++ b/selfprivacy_api/services/ocserv/__init__.py @@ -9,8 +9,8 @@ from selfprivacy_api.services.generic_status_getter import get_service_status from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceStatus from selfprivacy_api.utils import ReadUserData, WriteUserData from selfprivacy_api.utils.block_devices import BlockDevice -from selfprivacy_api.utils.network import get_ip4 from selfprivacy_api.services.ocserv.icon import OCSERV_ICON +import selfprivacy_api.utils.network as network_utils class Ocserv(Service): @@ -98,7 +98,20 @@ class Ocserv(Service): @staticmethod def get_dns_records() -> typing.List[ServiceDnsRecord]: - return [] + return [ + ServiceDnsRecord( + type="A", + name="vpn", + content=network_utils.get_ip4(), + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="vpn", + content=network_utils.get_ip6(), + ttl=3600, + ), + ] @staticmethod def get_storage_usage() -> int: diff --git a/selfprivacy_api/services/pleroma/__init__.py b/selfprivacy_api/services/pleroma/__init__.py index 1604fb4..97c11f5 100644 --- a/selfprivacy_api/services/pleroma/__init__.py +++ b/selfprivacy_api/services/pleroma/__init__.py @@ -9,7 +9,7 @@ from selfprivacy_api.services.generic_status_getter import get_service_status from selfprivacy_api.services.service import Service, ServiceDnsRecord, ServiceStatus from selfprivacy_api.utils import ReadUserData, WriteUserData, get_domain from selfprivacy_api.utils.block_devices import BlockDevice -from selfprivacy_api.utils.network import get_ip4 +import selfprivacy_api.utils.network as network_utils from selfprivacy_api.services.pleroma.icon import PLEROMA_ICON @@ -117,7 +117,13 @@ class Pleroma(Service): ServiceDnsRecord( type="A", name="social", - content=get_ip4(), + content=network_utils.get_ip4(), + ttl=3600, + ), + ServiceDnsRecord( + type="AAAA", + name="social", + content=network_utils.get_ip6(), ttl=3600, ), ] diff --git a/selfprivacy_api/utils/auth.py b/selfprivacy_api/utils/auth.py index d059d38..ecaf9af 100644 --- a/selfprivacy_api/utils/auth.py +++ b/selfprivacy_api/utils/auth.py @@ -88,7 +88,7 @@ def is_token_name_pair_valid(token_name, token): return False -def get_token_name(token): +def get_token_name(token: str) -> typing.Optional[str]: """Return the name of the token provided""" with ReadUserData(UserDataFiles.TOKENS) as tokens: for t in tokens["tokens"]: