7 Commits

Author SHA1 Message Date
Alexey Kovrizhkin
07d873eb11 update for actual _lib code 2023-07-08 21:44:11 +03:00
Alexey Kovrizhkin
04249284cc * fix: replace INT -> BIGINT in domain_id(), acme_insert()
* add: soa_mk(), csum_exists()
2023-07-08 21:43:26 +03:00
Alexey Kovrizhkin
df8cdda608 fix: clean removes OBJECTS 2023-07-08 21:39:43 +03:00
Alexey Kovrizhkin
f937028c2b upd: comments and spaces 2023-07-08 15:40:31 +03:00
Aleksei Kovrizhkin
b35df3328c Merge pull request #1 from anp135/master
server specific MNAME
2023-06-30 20:29:23 +03:00
135
35087ccc6b put new variable NSERVER to sql 2023-06-30 16:40:27 +03:00
135
0c71240182 Use own MNAME because no primary/secondary logic exists (https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.13). So each service should use own MNAME. 2023-06-30 16:09:38 +03:00
4 changed files with 102 additions and 37 deletions

View File

@@ -26,6 +26,9 @@ PGPASSWORD ?=
#- ACME zone suffix
ACME_DOMAIN ?=
#- This NS hostname for use in all SOA
NSERVER ?=
# ------------------------------------------------------------------------------
all: help
@@ -50,7 +53,7 @@ update: $(OBJECTS)
%.done: %.sql
@echo "*** $< ***"
@csum=$$(md5sum $< | sed 's/ .*//') ; \
cat $< | docker exec -i $$PG_CONTAINER psql -U $$PGUSER -d $$PGDATABASE -vcsum=$$csum -vACME_DOMAIN=$(ACME_DOMAIN) > $@
cat $< | docker exec -i $$PG_CONTAINER psql -U $$PGUSER -d $$PGDATABASE -vcsum=$$csum -vACME_DOMAIN=$(ACME_DOMAIN) -vNSERVER=$(NSERVER) > $@
## Load updated zone files via psql connection
update-direct: $(CFG) $(OBJECTSDIRECT)
@@ -94,7 +97,7 @@ config: $(CFG).sample
## Remove .done files
clean:
rm -rf *.done
rm -rf $(OBJECTS)
# This code handles group header and target comment with one or two lines only
## list Makefile targets

View File

@@ -40,7 +40,10 @@ SELECT x, soa_upd(x) FROM unnest(ARRAY[
]) x;
*/
CREATE OR REPLACE FUNCTION domain_id(a_name TEXT, a_type TEXT DEFAULT 'NATIVE') RETURNS INTEGER AS $_$
-- result was changed to bigint
DROP FUNCTION IF EXISTS domain_id(text,text);
CREATE OR REPLACE FUNCTION domain_id(a_name TEXT, a_type TEXT DEFAULT 'NATIVE') RETURNS BIGINT AS $_$
/*
Вернуть ID домена, создав его при необходимости
*/
@@ -58,7 +61,7 @@ BEGIN
END
$_$ LANGUAGE plpgsql;
CREATE OR REPLACE PROCEDURE acme_insert(a_domain_id INT, a_name TEXT, a_ip TEXT, a_ttl INT) AS $_$
CREATE OR REPLACE PROCEDURE acme_insert(a_domain_id BIGINT, a_name TEXT, a_ip TEXT, a_ttl INT) AS $_$
/*
Добавление в зону для заданного a_ip записей для передачи ему контроля над зоной a_name.
Это используется в DNS-01 challenge ACME
@@ -76,3 +79,70 @@ BEGIN
;
END;
$_$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION soa_mk(
a_domain_id BIGINT
, a_ns_admin TEXT
, a_refresh INTEGER DEFAULT 10800 -- 3 hours
, a_retry INTEGER DEFAULT 3600 -- 1 hour
, a_expire INTEGER DEFAULT 604800 -- 7 days
, a_ttl INTEGER DEFAULT 1800 -- 30 min
) RETURNS TEXT AS $_$
/*
Получить новый серийный номер зоны, проверить наличие NSERVER и вернуть строку SOA
refresh -- time lag until the slave again asks the master for a current version of the zone file
retry -- Should this request go unanswered, the “Retry” field regulates when a new attempt is to be carried out (< refresh)
expire -- determines how long the zone file may still be used before the server refuses DNS information delivery
ttl -- how long a client may hold the requested information in the cache before a new request must be sent
Each value in seconds
*/
DECLARE
v_ns text := current_setting('vars.ns'); -- master DNS host
v_stamp text; -- zone SOA timestamp
v_stamp_old text; -- previous zone SOA timestamp
BEGIN
-- check NSERVER
IF coalesce(v_ns,'') = '' THEN
RAISE EXCEPTION 'NSERVER is not set';
END IF;
-- calculate SOA with next serial
SELECT INTO v_stamp_old split_part(content, ' ', 3) FROM records WHERE domain_id = a_domain_id AND type = 'SOA';
v_stamp := soa_upd(v_stamp_old);
RETURN concat_ws(' ', v_ns, a_ns_admin, v_stamp, a_refresh, a_retry, a_expire, a_ttl);
END;
$_$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION csum_exists(a_domain_id BIGINT) RETURNS BOOL AS $_$
/*
Проверить совпадение vars.csum с загруженным в БД прошлый раз.
Если нет таблицы dcape_csum - создать ее
Если csum отличается - обновить
*/
DECLARE
v_csum text := current_setting('vars.csum'); -- file csum
v_csum_old text;
BEGIN
RAISE NOTICE 'Source csum: %', v_csum;
IF to_regclass('public.dcape_csum') IS NULL THEN
CREATE TABLE dcape_csum(
domain_id bigint primary key REFERENCES domains(id) ON DELETE CASCADE
, csum text
, updated_at timestamptz(0)
);
ELSE
SELECT INTO v_csum_old csum FROM dcape_csum WHERE domain_id = a_domain_id;
END IF;
IF v_csum_old IS NULL THEN
INSERT INTO dcape_csum(domain_id, csum, updated_at) VALUES (a_domain_id, v_csum, now());
ELSIF v_csum_old <> v_csum THEN
UPDATE dcape_csum SET csum = v_csum, updated_at = now() WHERE domain_id = a_domain_id;
ELSE
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$_$ LANGUAGE plpgsql;

View File

@@ -8,11 +8,14 @@
-- This var must be set in psql args
SET vars.domain TO :'ACME_DOMAIN';
-- This zone copy hostname
SET vars.ns TO :'NSERVER';
DO $_$
DECLARE
v_domain text := 'acme-' || current_setting('vars.domain'); -- domain name
v_ns text := 'ns.' || current_setting('vars.domain'); -- master DNS host
v_ns_admin text := 'admin.'|| current_setting('vars.domain'); -- master DNS admin email
v_ns text := current_setting('vars.ns'); -- master DNS host
v_refresh int := 10800;
v_retry int := 3600;
@@ -20,8 +23,6 @@ DECLARE
v_ttl int := 1800;
v_domain_id integer; -- internal domain id
v_stamp text; -- zone timestamp
v_stamp_old text; -- previous zone SOA timestamp
v_soa text; -- zone SOA
BEGIN
@@ -31,12 +32,12 @@ BEGIN
RETURN;
END IF;
RAISE NOTICE 'Setup acme zone % for nameserver %',v_domain,v_ns;
RAISE NOTICE 'Setup acme zone % for nameserver %', v_domain, v_ns;
SELECT INTO v_domain_id id FROM domains WHERE name = v_domain;
IF FOUND THEN
-- no any changes needed after creation
RAISE NOTICE 'Zone already exists. Skipping';
RAISE NOTICE 'Zone % already exists. Skipping', v_domain;
RETURN;
END IF;

View File

@@ -2,49 +2,40 @@
Complete PowerDNS zone records
*/
-- This file control sum
SET vars.csum TO :'csum';
-- This zone copy hostname
SET vars.ns TO :'NSERVER';
DO $_$
DECLARE
v_domain text := 'dev.lan'; -- domain name
v_ns_admin text := 'admin.ns.dev.lan'; -- master DNS admin email
v_ip text := '127.0.0.1'; -- base ip
v_ip1 text := '127.0.1.1'; -- some another ip
v_ns text := 'ns.dev.lan'; -- master DNS host
v_ns_admin text := 'admin.ns.dev.lan'; -- master DNS admin email
v_ttl INTEGER := 60; -- 1 min
v_domain_id integer; -- internal domain id
v_stamp text; -- zone SOA timestamp
v_stamp_old text; -- previous zone SOA timestamp
v_soa text; -- zone SOA
v_refresh int := 10800;
v_retry int := 3600;
v_expire int := 604800;
v_ttl int := 1800;
/*
refresh -- time lag until the slave again asks the master for a current version of the zone file
retry -- Should this request go unanswered, the “Retry” field regulates when a new attempt is to be carried out (< refresh)
expire -- determines how long the zone file may still be used before the server refuses DNS information delivery
ttl -- how long a client may hold the requested information in the cache before a new request must be sent
Each value in seconds
*/
BEGIN
v_domain_id := domain_id(v_domain);
-- calculate SOA with next serial
SELECT INTO v_stamp_old split_part(content, ' ', 3) FROM records WHERE domain_id = v_domain_id AND type = 'SOA';
v_stamp := soa_upd(v_stamp_old);
v_soa := concat_ws(' ', v_ns, v_ns_admin, v_stamp, v_refresh, v_retry, v_expire, v_ttl);
-- check csum, do not run twice
IF csum_exists(v_domain_id) THEN
RAISE NOTICE 'Domain % does not changed. Skipping', v_domain;
RETURN;
END IF;
-- clear zone
DELETE FROM records WHERE domain_id = v_domain_id;
v_soa := soa_mk(v_domain_id, v_ns_admin);
-- all zone records are following here
INSERT INTO records (domain_id, name, ttl, type, prio, content) VALUES
(v_domain_id, v_domain, 60, 'SOA', 0, v_soa)
(v_domain_id, v_domain, v_ttl, 'SOA', 0, v_soa)
, (v_domain_id, v_domain, v_ttl, 'NS', 0, 'ns.' || v_domain)
, (v_domain_id, v_domain, v_ttl, 'MX', 5, 'mail.' || v_domain)
, (v_domain_id, v_domain, v_ttl,'TXT', 0, 'v=spf1 mx ~all')
, (v_domain_id, v_domain, v_ttl, 'TXT', 0, '"v=spf1 mx ~all"')
, (v_domain_id, v_domain, v_ttl, 'A', 0, v_ip)
, (v_domain_id, 'www.' || v_domain, v_ttl, 'A', 0, v_ip)