Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55b45642e4 | ||
|
|
e3ded07a44 | ||
|
|
1983467640 | ||
|
|
5ce2895ddf | ||
|
|
5665d001d4 | ||
|
|
3c61753bd3 | ||
|
|
8862bb2bc8 | ||
| 2794a48901 | |||
|
|
07d873eb11 | ||
|
|
04249284cc | ||
|
|
df8cdda608 | ||
|
|
f937028c2b | ||
|
|
b35df3328c | ||
| 35087ccc6b | |||
| 0c71240182 |
23
.drone.yml
23
.drone.yml
@@ -1,23 +0,0 @@
|
|||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: powerdns
|
|
||||||
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: deploy_local
|
|
||||||
pull: never
|
|
||||||
image: ${DCAPE_COMPOSE}
|
|
||||||
commands:
|
|
||||||
- . setup config
|
|
||||||
- make update
|
|
||||||
volumes:
|
|
||||||
- name: dockersock
|
|
||||||
path: /var/run/docker.sock
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- name: dockersock
|
|
||||||
host:
|
|
||||||
path: /var/run/docker.sock
|
|
||||||
|
|
||||||
# docker run powerdns pdnsutil check-zone
|
|
||||||
23
.woodpecker.yml
Normal file
23
.woodpecker.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
# lint this file
|
||||||
|
# go install github.com/woodpecker-ci/woodpecker/cmd/cli@latest
|
||||||
|
# cli lint .woodpecker.yml
|
||||||
|
|
||||||
|
variables:
|
||||||
|
- &dcape_img 'dcape-compose'
|
||||||
|
|
||||||
|
clone:
|
||||||
|
git:
|
||||||
|
image: woodpeckerci/plugin-git
|
||||||
|
settings:
|
||||||
|
lfs: false
|
||||||
|
tags: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
deploy:
|
||||||
|
image: *dcape_img
|
||||||
|
commands:
|
||||||
|
- make .config-link
|
||||||
|
- make update
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
105
Makefile
105
Makefile
@@ -1,9 +1,10 @@
|
|||||||
# app custom Makefile
|
# app dcape v3 dns-config Makefile.
|
||||||
|
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
CFG = .env
|
CFG = .env
|
||||||
|
CFG_BAK ?= $(CFG).bak
|
||||||
|
|
||||||
SOURCES ?= $(wildcard *.sql)
|
SOURCES ?= _lib.sql $(wildcard *.sql)
|
||||||
OBJECTS = $(SOURCES:.sql=.done)
|
OBJECTS = $(SOURCES:.sql=.done)
|
||||||
OBJECTSDIRECT = $(SOURCES:.sql=.direct)
|
OBJECTSDIRECT = $(SOURCES:.sql=.direct)
|
||||||
|
|
||||||
@@ -11,96 +12,76 @@ OBJECTSDIRECT = $(SOURCES:.sql=.direct)
|
|||||||
# app custom config
|
# app custom config
|
||||||
# comments prefixed with '#- ' will be copied to $(CFG).sample
|
# comments prefixed with '#- ' will be copied to $(CFG).sample
|
||||||
|
|
||||||
#- Postgresql container name (access via docker)
|
#- ACME zone suffix
|
||||||
PG_CONTAINER ?= dcape_db_1
|
ACME_DOMAIN ?=
|
||||||
|
|
||||||
|
#- This NS hostname for use in all SOA
|
||||||
|
NSERVER ?=
|
||||||
|
|
||||||
|
#- db container
|
||||||
|
DB_CONTAINER ?= #
|
||||||
|
|
||||||
#- PowerDNS DB user name
|
#- PowerDNS DB user name
|
||||||
PGUSER ?= pdns
|
PGUSER ?= pdns
|
||||||
|
|
||||||
#- PowerDNS DB name
|
#- PowerDNS DB name
|
||||||
PGDATABASE ?= pdns
|
PGDATABASE ?= pdns
|
||||||
|
|
||||||
#- Used ONLY for direct DB access without docker (update-direct)
|
#- Used ONLY for direct DB access without docker (update-direct)
|
||||||
PGPASSWORD ?=
|
PGPASSWORD ?=
|
||||||
|
#- Used ONLY for direct DB access without docker (update-direct)
|
||||||
|
DB_PORT_LOCAL ?=
|
||||||
|
|
||||||
#- ACME zone suffix
|
USE_DCAPE_DC := no
|
||||||
ACME_DOMAIN ?=
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
all: help
|
|
||||||
|
|
||||||
-include $(CFG)
|
-include $(CFG)
|
||||||
export
|
export
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# dcape v1 comparibility
|
|
||||||
|
|
||||||
start-hook: update
|
ifneq ($(findstring $(MAKECMDGOALS),psql),)
|
||||||
|
USE_DB := yes
|
||||||
stop:
|
else ifneq ($(findstring $(MAKECMDGOALS),psql-local),)
|
||||||
|
USE_DB := yes
|
||||||
|
ifndef DB_PORT_LOCAL
|
||||||
|
$(error "DB_PORT_LOCAL must be set - $(MAKECMDGOALS)")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
## Usage
|
# Find and include DCAPE_ROOT/Makefile
|
||||||
#:
|
#- dcape compose docker image
|
||||||
|
DCAPE_COMPOSE ?= dcape-compose
|
||||||
|
DCAPE_ROOT ?= $(shell docker inspect -f "{{.Config.Labels.dcape_root}}" $(DCAPE_COMPOSE))
|
||||||
|
|
||||||
|
ifeq ($(shell test -e $(DCAPE_ROOT)/Makefile.app && echo -n yes),yes)
|
||||||
|
include $(DCAPE_ROOT)/Makefile.app
|
||||||
|
else
|
||||||
|
include /opt/dcape/Makefile.app
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
## DB operations
|
||||||
|
#:
|
||||||
|
.PHONY: update
|
||||||
|
|
||||||
## Load updated zone files via running PG container
|
|
||||||
update: $(OBJECTS)
|
update: $(OBJECTS)
|
||||||
|
|
||||||
%.done: %.sql
|
%.done: %.sql
|
||||||
@echo "*** $< ***"
|
@echo "*** $< ***"
|
||||||
@csum=$$(md5sum $< | sed 's/ .*//') ; \
|
@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 $$DB_CONTAINER psql -U $$PGUSER -d $$PGDATABASE -vcsum=$$csum -vACME_DOMAIN=$(ACME_DOMAIN) -vNSERVER=$(NSERVER) > $@
|
||||||
|
|
||||||
## Load updated zone files via psql connection
|
## Load updated zone files via psql connection
|
||||||
update-direct: $(CFG) $(OBJECTSDIRECT)
|
update-direct: $(CFG) $(OBJECTSDIRECT)
|
||||||
|
|
||||||
%.direct: %.sql
|
%.direct: %.sql
|
||||||
@echo "*** $< ***"
|
@echo "*** $< ***"
|
||||||
@source $(CFG) && cat $< | PGPASSWORD=$$PGPASSWORD psql -h localhost -U $$PGUSER > $@
|
@source $(CFG) && cat $< | PGPASSWORD=$${PGPASSWORD:?Must be set} psql -h localhost -U $$PGUSER -p $${DB_PORT_LOCAL:?Must be set} > $@
|
||||||
|
|
||||||
## Run psql via running PG container
|
|
||||||
psql:
|
|
||||||
@docker exec -it $$PG_CONTAINER psql -U $$PGUSER $$PGDATABASE
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
## Other
|
|
||||||
#:
|
|
||||||
|
|
||||||
# This code generates $(CFG).sample from Makefile vars with previous comment line(s)
|
|
||||||
# See https://gist.github.com/LeKovr/2697fe02504d7c081b0bf79427c93db6
|
|
||||||
|
|
||||||
# Internal: generate config sample data
|
|
||||||
.env.temp.mk:
|
|
||||||
@echo "define CFVAR" > $@
|
|
||||||
@grep -A 1 -h "^#- " $(MAKEFILE_LIST) | grep -vE "^--" \
|
|
||||||
| sed -E 's/^([^\n ]+)\ *\??=([^\n]*)$$/\1=$$(\1)\n/ ; s/^(#)-/\1/' >> $@
|
|
||||||
@echo "endef" >> $@
|
|
||||||
|
|
||||||
ifneq ($(findstring $(MAKECMDGOALS),config $(CFG).sample),)
|
|
||||||
include .env.temp.mk
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Internal: generate config sample
|
|
||||||
$(CFG).sample: .env.temp.mk
|
|
||||||
@echo "# dcape-dns config file, generated by 'make config'\n" > $@
|
|
||||||
@echo "$$CFVAR" >> $@
|
|
||||||
@rm -f $<
|
|
||||||
|
|
||||||
## generate sample config
|
|
||||||
config: $(CFG).sample
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
## Remove .done files
|
## Remove .done files
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.done
|
rm -rf $(OBJECTS)
|
||||||
|
|
||||||
# This code handles group header and target comment with one or two lines only
|
|
||||||
## list Makefile targets
|
|
||||||
## (this is default target)
|
|
||||||
help:
|
|
||||||
@grep -A 1 -h "^## " $(MAKEFILE_LIST) \
|
|
||||||
| sed -E 's/^--$$// ; /./{H;$$!d} ; x ; s/^\n## ([^\n]+)\n(## (.+)\n)*(.+):(.*)$$/" " "\4" "\1" "\3"/' \
|
|
||||||
| sed -E 's/^" " "#" "(.+)" "(.*)"$$/"" "" "" ""\n"\1 \2" "" "" ""/' \
|
|
||||||
| xargs printf "%s\033[36m%-15s\033[0m %s %s\n"
|
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ This project contains Makefile and sample sql zone definition for loading zones
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* [dcape](https://github.com/TenderPro/dcape) installed on remote host with pdns and gitea running
|
* linux 64bit (git, make, wget, gawk, openssl)
|
||||||
|
* [docker](http://docker.io)
|
||||||
|
* [dcape](https://github.com/dopos/dcape)
|
||||||
|
* Git service ([github](https://github.com), [gitea](https://gitea.io) or [gogs](https://gogs.io))
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
87
_lib.sql
87
_lib.sql
@@ -40,7 +40,10 @@ SELECT x, soa_upd(x) FROM unnest(ARRAY[
|
|||||||
]) x;
|
]) 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 домена, создав его при необходимости
|
Вернуть ID домена, создав его при необходимости
|
||||||
*/
|
*/
|
||||||
@@ -58,17 +61,20 @@ BEGIN
|
|||||||
END
|
END
|
||||||
$_$ LANGUAGE plpgsql;
|
$_$ 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.
|
Добавление в зону для заданного a_ip записей для передачи ему контроля над зоной a_name.
|
||||||
Это используется в DNS-01 challenge ACME
|
Это используется в DNS-01 ACME challenge в конфигурации, когда на отдельный a_ip выносятся
|
||||||
|
* все сервисы домена (их имена - a_name и *.a_name)
|
||||||
|
* DNS сервис для обновления сертификатов (ns.a_name)
|
||||||
|
В этом случае traefik при обновлении сертификатов будет прописывать в спец. зоне ключи через API (power)dns сервера.
|
||||||
*/
|
*/
|
||||||
BEGIN
|
BEGIN
|
||||||
WITH acme(name, type, content) AS (VALUES
|
WITH acme(name, type, content) AS (VALUES
|
||||||
( a_name, 'A', a_ip)
|
( a_name, 'A', a_ip) -- зону резолвим в a_ip
|
||||||
, ('*.' || a_name, 'A', a_ip)
|
, ('*.' || a_name, 'A', a_ip) -- wildcard зоны резолвим в a_ip
|
||||||
, ('acme-' || a_name, 'NS', 'ns.' || a_name)
|
, ('acme-' || a_name, 'NS', 'ns.' || a_name) -- создаем специальную зону для DNS-01, её резолвит NS сервер, доступный по a_ip
|
||||||
, ('_acme-challenge.' || a_name, 'CNAME', 'acme-' || a_name)
|
, ('_acme-challenge.' || a_name, 'CNAME', 'acme-' || a_name) -- делегируем DNS-01 зоны a_name в специальную зону
|
||||||
)
|
)
|
||||||
INSERT INTO records (domain_id, name, ttl, type, prio, content)
|
INSERT INTO records (domain_id, name, ttl, type, prio, content)
|
||||||
SELECT a_domain_id, name, a_ttl, type, 0, content
|
SELECT a_domain_id, name, a_ttl, type, 0, content
|
||||||
@@ -76,3 +82,70 @@ BEGIN
|
|||||||
;
|
;
|
||||||
END;
|
END;
|
||||||
$_$ LANGUAGE plpgsql;
|
$_$ 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;
|
||||||
|
|||||||
@@ -8,11 +8,14 @@
|
|||||||
-- This var must be set in psql args
|
-- This var must be set in psql args
|
||||||
SET vars.domain TO :'ACME_DOMAIN';
|
SET vars.domain TO :'ACME_DOMAIN';
|
||||||
|
|
||||||
|
-- This zone copy hostname
|
||||||
|
SET vars.ns TO :'NSERVER';
|
||||||
|
|
||||||
DO $_$
|
DO $_$
|
||||||
DECLARE
|
DECLARE
|
||||||
v_domain text := 'acme-' || current_setting('vars.domain'); -- domain name
|
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_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_refresh int := 10800;
|
||||||
v_retry int := 3600;
|
v_retry int := 3600;
|
||||||
@@ -20,8 +23,6 @@ DECLARE
|
|||||||
v_ttl int := 1800;
|
v_ttl int := 1800;
|
||||||
|
|
||||||
v_domain_id integer; -- internal domain id
|
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
|
v_soa text; -- zone SOA
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -31,12 +32,12 @@ BEGIN
|
|||||||
RETURN;
|
RETURN;
|
||||||
END IF;
|
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;
|
SELECT INTO v_domain_id id FROM domains WHERE name = v_domain;
|
||||||
IF FOUND THEN
|
IF FOUND THEN
|
||||||
-- no any changes needed after creation
|
-- no any changes needed after creation
|
||||||
RAISE NOTICE 'Zone already exists. Skipping';
|
RAISE NOTICE 'Zone % already exists. Skipping', v_domain;
|
||||||
RETURN;
|
RETURN;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
|||||||
90
arpa.sql
Normal file
90
arpa.sql
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
-- This file control sum
|
||||||
|
SET vars.csum TO :'csum';
|
||||||
|
-- This zone copy hostname
|
||||||
|
SET vars.ns TO :'NSERVER';
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
-- Наполнение
|
||||||
|
|
||||||
|
DECLARE
|
||||||
|
v_domain text; -- domain name
|
||||||
|
v_domain_id integer; -- internal domain id
|
||||||
|
v_ns_admin text := 'hostmaster.example.ru'; -- master DNS admin email
|
||||||
|
v_soa text; -- zone SOA
|
||||||
|
v_prefixes cidr[] := ARRAY[
|
||||||
|
'10.0.0.0/8', -- Private-Use Networks
|
||||||
|
'100.64.0.0/10', -- CG-NAT
|
||||||
|
'127.0.0.0/8', -- Loopback
|
||||||
|
'172.16.0.0/12', -- LLA
|
||||||
|
'169.254.0.0/16', -- Private-Use Networks
|
||||||
|
'192.0.0.0/24', -- IETF Protocol Assignments
|
||||||
|
'192.0.2.0/24', -- TEST-NET-1
|
||||||
|
'192.88.99.0/24', -- 6to4 Relay Anycast
|
||||||
|
'192.168.0.0/16', -- Private-Use Networks
|
||||||
|
'198.18.0.0/15', -- Network Interconnect Device Benchmark Testing
|
||||||
|
'198.51.100.0/24', -- TEST-NET-2
|
||||||
|
'203.0.113.0/24' -- TEST-NET-3
|
||||||
|
];
|
||||||
|
v_prefixes24 cidr[];
|
||||||
|
v_prefix cidr;
|
||||||
|
v_arr text[];
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
-- пересобираем список префиксов по /24
|
||||||
|
-- ToDo: префиксы выходящие за границы /8 =< prefix < /24 пропускать
|
||||||
|
FOREACH v_prefix IN ARRAY v_prefixes LOOP
|
||||||
|
-- получили размерность
|
||||||
|
FOR i IN 0 .. 2^(24 - masklen(v_prefix))-1 LOOP
|
||||||
|
-- добавили каждую /24
|
||||||
|
v_prefixes24 := ARRAY_APPEND(v_prefixes24, set_masklen(v_prefix + 256 * i, 24));
|
||||||
|
-- RAISE NOTICE '% %: %', v_prefix, i, set_masklen(v_prefix + 256 * i, 24);
|
||||||
|
END LOOP;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
FOREACH v_prefix IN ARRAY v_prefixes24 LOOP
|
||||||
|
-- собираем имя зоны
|
||||||
|
v_domain := concat_ws('.', -- собираем полностью итоговый v_domain в формате $oct3.$oct2.$oct1.in-addr.arpa
|
||||||
|
array_to_string( -- результат превращаем в текст
|
||||||
|
array_reverse( -- разворачиваем массив в обратном направлении для in-addr.arpa
|
||||||
|
trim_array( -- отрезаем от массива последний октет с маской, так как для /24 в in-addr.arpa надо 3 октета
|
||||||
|
string_to_array(v_prefix::text, '.'), -- v_prefix переводим в text и разбираем в массив через '.'
|
||||||
|
1
|
||||||
|
)
|
||||||
|
),'.'
|
||||||
|
),
|
||||||
|
'in-addr.arpa'
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT INTO v_domain_id id FROM domains WHERE name = v_domain;
|
||||||
|
IF NOT FOUND THEN
|
||||||
|
-- зона отсутствует, будем генерить зону по умолчанию
|
||||||
|
RAISE NOTICE 'Stub generator for prefix:% zone:%', v_prefix, v_domain;
|
||||||
|
ELSE
|
||||||
|
-- зона уже создана, пропустить stub-функционал
|
||||||
|
RAISE NOTICE 'zone:% already exists, skip stub generation', v_domain;
|
||||||
|
CONTINUE;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
/*
|
||||||
|
чексуммы у зоны нет, поэтому достаточно будет первого запуска по
|
||||||
|
файлу со спецификой зоны, чтобы затереть зону-заглушку
|
||||||
|
получаем/создаём домен ID
|
||||||
|
*/
|
||||||
|
v_domain_id := domain_id(v_domain);
|
||||||
|
|
||||||
|
-- собираем SOA
|
||||||
|
v_soa := soa_mk(v_domain_id, v_ns_admin);
|
||||||
|
|
||||||
|
-- в принципе если мы здесь, то предполагается, что зоны такой не существовало
|
||||||
|
-- и записей, соответственно, нет. но тем не менее
|
||||||
|
DELETE FROM records WHERE domain_id = v_domain_id;
|
||||||
|
|
||||||
|
-- генерим зону по умолчанию
|
||||||
|
INSERT INTO records (domain_id, name, ttl, type, prio, content) VALUES
|
||||||
|
(v_domain_id, v_domain, 10800, 'SOA', 0, v_soa)
|
||||||
|
, (v_domain_id, v_domain, 10800, 'NS', 0, 'ns1.example.ru')
|
||||||
|
, (v_domain_id, v_domain, 10800, 'NS', 0, 'ns2.example.ru')
|
||||||
|
;
|
||||||
|
END LOOP;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
@@ -2,49 +2,40 @@
|
|||||||
Complete PowerDNS zone records
|
Complete PowerDNS zone records
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
-- This file control sum
|
||||||
|
SET vars.csum TO :'csum';
|
||||||
|
-- This zone copy hostname
|
||||||
|
SET vars.ns TO :'NSERVER';
|
||||||
|
|
||||||
DO $_$
|
DO $_$
|
||||||
DECLARE
|
DECLARE
|
||||||
v_domain text := 'dev.lan'; -- domain name
|
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_ip text := '127.0.0.1'; -- base ip
|
||||||
v_ip1 text := '127.0.1.1'; -- some another ip
|
v_ip1 text := '127.0.1.1'; -- some another ip
|
||||||
v_ns text := 'ns.dev.lan'; -- master DNS host
|
v_ttl INTEGER := 60; -- 1 min
|
||||||
v_ns_admin text := 'admin.ns.dev.lan'; -- master DNS admin email
|
|
||||||
v_domain_id integer; -- internal domain id
|
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_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
|
BEGIN
|
||||||
v_domain_id := domain_id(v_domain);
|
v_domain_id := domain_id(v_domain);
|
||||||
|
|
||||||
-- calculate SOA with next serial
|
-- check csum, do not run twice
|
||||||
SELECT INTO v_stamp_old split_part(content, ' ', 3) FROM records WHERE domain_id = v_domain_id AND type = 'SOA';
|
IF csum_exists(v_domain_id) THEN
|
||||||
v_stamp := soa_upd(v_stamp_old);
|
RAISE NOTICE 'Domain % does not changed. Skipping', v_domain;
|
||||||
v_soa := concat_ws(' ', v_ns, v_ns_admin, v_stamp, v_refresh, v_retry, v_expire, v_ttl);
|
RETURN;
|
||||||
|
END IF;
|
||||||
|
|
||||||
-- clear zone
|
-- clear zone
|
||||||
DELETE FROM records WHERE domain_id = v_domain_id;
|
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
|
-- all zone records are following here
|
||||||
INSERT INTO records (domain_id, name, ttl, type, prio, content) VALUES
|
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, 'NS', 0, 'ns.' || v_domain)
|
||||||
, (v_domain_id, v_domain, v_ttl, 'MX', 5, 'mail.' || 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, v_domain, v_ttl, 'A', 0, v_ip)
|
||||||
, (v_domain_id, 'www.' || v_domain, v_ttl, 'A', 0, v_ip)
|
, (v_domain_id, 'www.' || v_domain, v_ttl, 'A', 0, v_ip)
|
||||||
|
|||||||
Reference in New Issue
Block a user