Browse Source
new: [bind] add charm
new: [bind] add charm
Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>pull/29/head
Valentin Lab
2 years ago
16 changed files with 890 additions and 0 deletions
-
93bind/README.org
-
7bind/build/Dockerfile
-
120bind/hooks/init
-
50bind/hooks/log_rotate-relation-joined
-
331bind/lib/common
-
27bind/metadata.yaml
-
12bind/src/etc/bind/db.0
-
13bind/src/etc/bind/db.127
-
12bind/src/etc/bind/db.255
-
14bind/src/etc/bind/db.empty
-
14bind/src/etc/bind/db.local
-
88bind/src/etc/bind/db.root
-
3bind/src/etc/bind/named.conf
-
30bind/src/etc/bind/named.conf.default-zones
-
56bind/src/etc/bind/named.conf.options
-
20bind/src/etc/bind/zones.rfc1918
@ -0,0 +1,93 @@ |
|||||
|
# -*- ispell-local-dictionary: "english" -*- |
||||
|
|
||||
|
#+TITLE: Bind v9 Domain name server |
||||
|
|
||||
|
|
||||
|
* Usage |
||||
|
|
||||
|
** Example =compose.yml= |
||||
|
|
||||
|
#+begin_src yaml |
||||
|
dns: |
||||
|
charm: bind |
||||
|
|
||||
|
options: |
||||
|
vars: |
||||
|
## these vars are a facility to allow using `$var` in domain defs |
||||
|
myip: 1.2.3.4 |
||||
|
zones: |
||||
|
## __all__ will be applied to all domains defined here |
||||
|
__all__: |
||||
|
ns: |
||||
|
## '_' is translated to '@' in BIND v9 zone definition, which in |
||||
|
## in turn refers to the current domain being defined. |
||||
|
_: (dns.mycompany.com,sdns1.ovh.net,ns6.gandi.net) |
||||
|
mx: |
||||
|
_: (1 ,(5 alt(1,2),10 alt(3,4)).)aspmx.l.google.com. |
||||
|
mycompany.com: |
||||
|
mx: |
||||
|
news: 10 news |
||||
|
|
||||
|
## Names will generate IN A/CNAME depending if an IP is detected or a name |
||||
|
name: |
||||
|
## key and values can be expanded, the syntax uses the same logic |
||||
|
## than shell expansion with `{`, `}` and `,`. So this: |
||||
|
## `(_,dns,core(,-01))` will demux to `_ dns core core-01`, so all |
||||
|
## these keys will receive the following value. |
||||
|
(_,dns,core(,-01)): $myip |
||||
|
core-02: 4.5.6.7 |
||||
|
|
||||
|
## You can specify after a space, a TTL that will be applied to all |
||||
|
## definitions inside the section: |
||||
|
name 3h: |
||||
|
## `www` required not to be an IP by zonecheck |
||||
|
(www,admin,smtp,beta,alpha,erp(,-beta)): core-01 |
||||
|
news: 77.32.131.26 |
||||
|
r.news: r.mailin.fr. |
||||
|
img.news: img.mailin.fr. |
||||
|
|
||||
|
spf 3h: |
||||
|
## Remember that this is YAML that also offer nice syntaxic |
||||
|
## feature to avoid repeating values. |
||||
|
_: &spf >- |
||||
|
v=spf1 a |
||||
|
a:smtp.free.fr |
||||
|
a:smtp.mycompany.com |
||||
|
include:spf.sendinblue.com |
||||
|
mx ?all |
||||
|
txt 3h: |
||||
|
_: |
||||
|
- *spf |
||||
|
- Sendinblue-code:xxx |
||||
|
- google-site-verification=yyy |
||||
|
|
||||
|
news: "v=spf1 include:spf.sendinblue.com mx ~all" |
||||
|
mail._domainkey(,.news): |
||||
|
"k=rsa;p=zzz" |
||||
|
|
||||
|
_dmarc.news: >- |
||||
|
v=DMARC1; |
||||
|
p=none; |
||||
|
sp=none; |
||||
|
rua=mailto:dmarc@mailinblue.com!10m; |
||||
|
ruf=mailto:dmarc@mailinblue.com!10m; |
||||
|
rf=afrf; |
||||
|
pct=100; |
||||
|
ri=86400 |
||||
|
|
||||
|
(othercompany.com,other-company.com): |
||||
|
name: |
||||
|
(_,www,mail): $myip |
||||
|
(admin,beta): www |
||||
|
#+end_src |
||||
|
|
||||
|
|
||||
|
* Persistence |
||||
|
|
||||
|
backup will keep: |
||||
|
- /etc/bind/rndc.key |
||||
|
- /etc/bind/.db.$DOMAIN files keeping a hash of the configuration along |
||||
|
with the given serial that matches the zone file. This is to be sure to |
||||
|
advertise the same serial after a recovery. |
||||
|
|
||||
|
|
@ -0,0 +1,7 @@ |
|||||
|
FROM alpine:3.12.0 |
||||
|
|
||||
|
RUN apk add --no-cache bind |
||||
|
|
||||
|
EXPOSE 53 |
||||
|
|
||||
|
CMD ["named", "-c", "/etc/bind/named.conf", "-g", "-u", "named"] |
@ -0,0 +1,120 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
## Init is run on host |
||||
|
## For now it is run every time the script is launched, but |
||||
|
## it should be launched only once after build. |
||||
|
|
||||
|
## Accessible variables are: |
||||
|
## - SERVICE_NAME Name of current service |
||||
|
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any |
||||
|
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service |
||||
|
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service |
||||
|
|
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## "${BIND_CONFIG_DIR}"/bind.keys |
||||
|
## |
||||
|
|
||||
|
## https://www.isc.org/bind-keys/ |
||||
|
|
||||
|
config_hash=$(docker inspect "$DOCKER_BASE_IMAGE" --format '{{ .Id }}') |
||||
|
if ! [ -e "${SERVICE_CONFIGSTORE}${BIND_CONFIG_DIR}"/bind.keys ]; then |
||||
|
mkdir -p "${SERVICE_CONFIGSTORE}${BIND_CONFIG_DIR}" |
||||
|
## From alpine install |
||||
|
ln -sf ../../usr/share/dnssec-root/bind-dnssec-root.keys \ |
||||
|
"${SERVICE_CONFIGSTORE}${BIND_CONFIG_DIR}"/bind.keys |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## "${BIND_CONFIG_DIR}"/rndc.key |
||||
|
## |
||||
|
|
||||
|
|
||||
|
if [ -d "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/rndc.key ]; then |
||||
|
## When deleting file and docker is still running, due to named |
||||
|
## stopping and docker force-restart, this file will be recreated |
||||
|
## as a directory To avoid issues, if we detect this condition, |
||||
|
## let's just remove the directory |
||||
|
|
||||
|
rmdir "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/rndc.key |
||||
|
fi |
||||
|
|
||||
|
if ! [ -e "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/rndc.key ]; then |
||||
|
mkdir -p "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/ |
||||
|
docker run --rm -v "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}:${BIND_CONFIG_DIR}" \ |
||||
|
"$DOCKER_BASE_IMAGE" rndc-confgen -b 256 -a |
||||
|
if ! [ -e "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/rndc.key ]; then |
||||
|
err "RNDC key-file generation failed." |
||||
|
exit 1 |
||||
|
fi |
||||
|
fi |
||||
|
config_hash=$(e "$config_hash" "$(cat "${SERVICE_DATASTORE}${BIND_CONFIG_DIR}"/rndc.key)") |
||||
|
|
||||
|
init-config-add " |
||||
|
$SERVICE_NAME: |
||||
|
volumes: |
||||
|
- \"$SERVICE_DATASTORE${BIND_CONFIG_DIR}/rndc.key:${BIND_CONFIG_DIR}/rndc.key:ro\" |
||||
|
" |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## "${BIND_CONFIG_DIR}"/named.conf and others |
||||
|
## |
||||
|
|
||||
|
|
||||
|
|
||||
|
cd src |
||||
|
cfg_files=("${BIND_CONFIG_DIR#/}"/{zones.rfc1918,{db,named}.*}) |
||||
|
for file in "${cfg_files[@]}"; do |
||||
|
if ! diff "$file" "$SERVICE_CONFIGSTORE"/"$file" >/dev/null 2>&1; then |
||||
|
cp -v "$file" "$SERVICE_CONFIGSTORE"/"$file" >&2 || exit 1 |
||||
|
else |
||||
|
echo "File $file already up to date." >&2 |
||||
|
fi |
||||
|
done |
||||
|
config_hash=$(p0 "$config_hash" "$(cat "${cfg_files[@]}")" | md5_compat) |
||||
|
cd .. |
||||
|
|
||||
|
## |
||||
|
## user requested zones |
||||
|
## |
||||
|
|
||||
|
vars_cfg=$(options-get vars 2>/dev/null) || true |
||||
|
zones_cfg=$(options-get zones 2>/dev/null) || true |
||||
|
|
||||
|
if [ -n "$zones_cfg" ]; then |
||||
|
## will update config_hash |
||||
|
bind:cfg:generate "$zones_cfg" "$vars_cfg" |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
uid=$(docker_get_uid "$SERVICE_NAME" "named") |
||||
|
|
||||
|
dirs=(/{etc,var/{log,cache}}/bind ) |
||||
|
host_dirs=() |
||||
|
for dir in "${dirs[@]}"; do |
||||
|
host_dirs+=("$SERVICE_DATASTORE$dir") |
||||
|
done |
||||
|
host_dirs+=("$SERVICE_CONFIGSTORE"/etc/bind) |
||||
|
|
||||
|
mkdir -p "${host_dirs[@]}" |
||||
|
find "${host_dirs[@]}" \! -user "$uid" -or -type l -print0 | while read-0 f; do |
||||
|
chown -v "$uid" "$f" || exit 1 |
||||
|
done |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## Final |
||||
|
## |
||||
|
|
||||
|
init-config-add " |
||||
|
$MASTER_BASE_SERVICE_NAME: |
||||
|
labels: |
||||
|
- compose.config_hash=$config_hash |
||||
|
" |
@ -0,0 +1,50 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
## Should be executable N time in a row with same result. |
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
named_uid=$(docker_get_uid "$SERVICE_NAME" "named") |
||||
|
|
||||
|
LOGS=/var/log/bind |
||||
|
mkdir -p "$SERVICE_DATASTORE/$LOGS" |
||||
|
chown -R "$named_uid" "$SERVICE_DATASTORE/$LOGS" |
||||
|
|
||||
|
rotated_count=$(relation-get rotated-count 2>/dev/null) || true |
||||
|
rotated_count=${rotated_count:-52} |
||||
|
|
||||
|
## XXXvlab: a lot of this intelligence should be moved away into ``logrotate`` charm |
||||
|
DST="$CONFIGSTORE/$TARGET_SERVICE_NAME/etc/logrotate.d/$SERVICE_NAME" |
||||
|
file_put "$DST" <<EOF |
||||
|
/var/log/docker/$SERVICE_NAME/*.log |
||||
|
{ |
||||
|
weekly |
||||
|
missingok |
||||
|
dateext |
||||
|
dateyesterday |
||||
|
dateformat _%Y-%m-%d |
||||
|
extension .log |
||||
|
rotate $rotated_count |
||||
|
compress |
||||
|
delaycompress |
||||
|
notifempty |
||||
|
create 640 |
||||
|
sharedscripts |
||||
|
postrotate |
||||
|
dc exec $SERVICE_NAME /usr/sbin/rndc reconfig > /dev/null 2>/dev/null || true |
||||
|
endscript |
||||
|
} |
||||
|
EOF |
||||
|
|
||||
|
config-add "\ |
||||
|
services: |
||||
|
$MASTER_TARGET_SERVICE_NAME: |
||||
|
volumes: |
||||
|
- $DST:/etc/logrotate.d/docker-${SERVICE_NAME}:ro |
||||
|
- $SERVICE_DATASTORE$LOGS:/var/log/docker/$SERVICE_NAME:rw |
||||
|
$MASTER_BASE_SERVICE_NAME: |
||||
|
volumes: |
||||
|
- $SERVICE_DATASTORE$LOGS:$LOGS:rw |
||||
|
" |
@ -0,0 +1,331 @@ |
|||||
|
# -*- mode: shell-script -*- |
||||
|
|
||||
|
BIND_CONFIG_DIR=/etc/bind |
||||
|
|
||||
|
|
||||
|
## Generate bind config files in $cfgdir from YAML configuration $cfg |
||||
|
bind:cfg:generate() { |
||||
|
local cfg="$1" vars="$2" zone_file include_zone_statements all_domain \ |
||||
|
domains expanded_domains zone_cfg |
||||
|
|
||||
|
## __all__ domain is treated here like a normal domain |
||||
|
|
||||
|
expanded_domains="" |
||||
|
while read-0 domain zone_cfg; do |
||||
|
if ! [[ "$domain" =~ ^[a-z0-9_\(\),.-]+$ ]]; then |
||||
|
err "Invalid domain '$domain' as key in ${WHITE}zones${NORMAL} records." |
||||
|
return 1 |
||||
|
fi |
||||
|
domains=() |
||||
|
bind:parse:expand-in "$domain" domains "$vars" || return 1 |
||||
|
for domain in "${domains[@]}"; do |
||||
|
expanded_domains=$(merge_yaml_str "$expanded_domains" \ |
||||
|
"$(yaml_key_val_str "$domain" "$zone_cfg")") |
||||
|
done |
||||
|
done < <(e "$cfg" | shyaml key-values-0) |
||||
|
|
||||
|
## __all__ domain is merged in other domain domain |
||||
|
|
||||
|
all_domain=$(e "$expanded_domains" | shyaml get-value "__all__") |
||||
|
resolved_domains="" |
||||
|
while read-0 domain zone_cfg; do |
||||
|
if [ "$domain" == "__all__" ]; then |
||||
|
continue |
||||
|
fi |
||||
|
resolved_domains=$(merge_yaml_str \ |
||||
|
"$resolved_domains" \ |
||||
|
"$(yaml_key_val_str "$domain" "$all_domain")" \ |
||||
|
"$(yaml_key_val_str "$domain" "$zone_cfg")") |
||||
|
done < <(e "$expanded_domains" | shyaml key-values-0) |
||||
|
|
||||
|
include_zone_statements= |
||||
|
while read-0 domain zone_cfg; do |
||||
|
info "Considering ${WHITE}$domain${NORMAL} zone configuration" |
||||
|
zone_file="${BIND_CONFIG_DIR}/db.${domain}" |
||||
|
zone_hash_file="${BIND_CONFIG_DIR}/.db.${domain}.hash" |
||||
|
zone_def=$(bind:content:zone_definition \ |
||||
|
"$domain" "$zone_cfg" "$vars") || return 1 |
||||
|
zone_def_hash=$(H "$zone_def") |
||||
|
|
||||
|
## We need to store the last serial as well as the last hash in |
||||
|
## the datastore to allow a full restore (will correct serials) |
||||
|
## without discontinuity of services. |
||||
|
|
||||
|
current_hash= |
||||
|
current_serial= |
||||
|
if [ -e "${SERVICE_DATASTORE}${zone_hash_file}" ]; then |
||||
|
current_hash_content="$(cat "${SERVICE_DATASTORE}${zone_hash_file}")" || true |
||||
|
current_hash=${current_hash_content% *} |
||||
|
current_serial=${current_hash_content#* } |
||||
|
echo " found a previous hash file with serial: $current_serial" >&2 |
||||
|
fi |
||||
|
|
||||
|
if [ "$current_hash" == "$zone_def_hash" ]; then ## no need to change full serial |
||||
|
echo " can use previous serial as zone definition seems to have not changed" >&2 |
||||
|
serial=${current_serial} |
||||
|
else |
||||
|
echo " needs a new serial as zone definition seems to have changed" >&2 |
||||
|
date=$(date +%Y%m%d) |
||||
|
if [ "$date" == "${current_serial:0:8}" ]; then |
||||
|
serial="$date$(printf "%02d" "$((${current_serial: -2:2} + 1))")" |
||||
|
echo " increment serial to $serial" >&2 |
||||
|
else |
||||
|
serial="${date}00" |
||||
|
echo " first definition for the current date" >&2 |
||||
|
fi |
||||
|
fi |
||||
|
zone_def=$(e "$zone_def" | sed -r "s/%%SERIAL%%/$serial/g") |
||||
|
if ! [ -e "${SERVICE_CONFIGSTORE}${zone_file}" ] || |
||||
|
[ "$zone_def" != "$(cat "${SERVICE_CONFIGSTORE}${zone_file}")" ]; then |
||||
|
echo " ${DARKYELLOW}writing${NORMAL} zone def file to config with serial $serial." >&2 |
||||
|
e "${zone_def}" > "${SERVICE_CONFIGSTORE}${zone_file}" |
||||
|
else |
||||
|
echo " zone def already available in config with serial $serial." >&2 |
||||
|
fi |
||||
|
if ! [ -e "${SERVICE_DATASTORE}${zone_hash_file}" ] || |
||||
|
[ "$zone_def_hash $serial" != "$(cat "${SERVICE_DATASTORE}${zone_hash_file}")" ]; then |
||||
|
echo " ${DARKYELLOW}writing${NORMAL} zone file hash to data with serial $serial." >&2 |
||||
|
e "$zone_def_hash $serial" > "${SERVICE_DATASTORE}${zone_hash_file}" |
||||
|
else |
||||
|
echo " zone def hash already available in data with serial $serial." >&2 |
||||
|
fi |
||||
|
|
||||
|
include_zone_statements+=$( |
||||
|
bind:content:include_zone_statement "$domain" "${zone_file}" |
||||
|
)$'\n' |
||||
|
config_hash=$(p0 "$config_hash" "$zone_def_hash" | md5_compat) || exit 1 |
||||
|
done < <(e "$resolved_domains" | shyaml key-values-0) |
||||
|
|
||||
|
e "$include_zone_statements" > "${SERVICE_CONFIGSTORE}${BIND_CONFIG_DIR}/named.conf.local" |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bind:content:include_zone_statement() { |
||||
|
local domain="$1" zone_file="$2" |
||||
|
|
||||
|
cat <<EOF |
||||
|
zone "${domain}" { |
||||
|
type master; |
||||
|
notify yes; |
||||
|
file "${zone_file}"; |
||||
|
}; |
||||
|
EOF |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bind:check:is_time() { |
||||
|
local label="$1" value="$2" |
||||
|
if ! [[ "$value" =~ ^[0-9smhdw]+$ ]]; then |
||||
|
err "Invalid value for $label: '$value'." >&2 |
||||
|
echo " Please use a number of seconds or use one-character time units (IE: 1w, 1h30, 3600)" >&2 |
||||
|
return 1 |
||||
|
fi |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
bind:parse:expand-in() { |
||||
|
local value="$1" aname="$2" vars="$3" |
||||
|
|
||||
|
if ! [[ "$value" =~ ^[a-z0-9_\(\)\ \$,.-]+$ ]]; then |
||||
|
err "Invalid value '$value' to expand." |
||||
|
return 1 |
||||
|
fi |
||||
|
declare -n cur="$aname" |
||||
|
if [[ "$value" == *","* ]]; then |
||||
|
value="${value//\(/\{}" |
||||
|
value="${value//\)/\}}" |
||||
|
value="${value// /\\ }" |
||||
|
else |
||||
|
value="\"$value\"" |
||||
|
fi |
||||
|
|
||||
|
value="${value//\$/\$_vars_}" |
||||
|
while read-0 label v; do |
||||
|
local "_vars_$label"="$v" |
||||
|
done < <(e "$vars" | shyaml key-values-0) |
||||
|
eval "cur+=($value)" || { |
||||
|
err "Couldn't eval '$value'." |
||||
|
return 1 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bind:content:zone_definition() { |
||||
|
local domain="$1" zone_cfg="$2" vars_cfg="$3" \ |
||||
|
vtype cache_file="$CACHEDIR/$FUNCNAME.cache.$(H "$@")" |
||||
|
if [ -e "$cache_file" ]; then |
||||
|
# debug "$FUNCNAME: cache hit ($*)" |
||||
|
cat "$cache_file" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
## Zone definition is created with %%SERIAL%% as placeholder in |
||||
|
## the serial number intended final emplacement. This allows to |
||||
|
## check the output's hash of this function to decide if we need |
||||
|
## to change the serial. |
||||
|
|
||||
|
zone_cfg=$(merge_yaml_str " |
||||
|
\$ttl: 1w |
||||
|
soa: |
||||
|
email: dns@${domain} |
||||
|
refresh: 8h |
||||
|
retry: 4h |
||||
|
expire: 1w |
||||
|
ttl: 1d |
||||
|
ns: |
||||
|
_: dns |
||||
|
" "$zone_cfg") || return 1 |
||||
|
|
||||
|
vars_cfg=$(merge_yaml_str " |
||||
|
mydomain: \"$domain\" |
||||
|
" "$vars_cfg") || return 1 |
||||
|
|
||||
|
while read-0 key subcfg; do |
||||
|
# echo "KEY: $key" >&2 |
||||
|
# echo "SUBCONFIG:" >&2 |
||||
|
# echo "$subcfg" | prefix " | " >&2 |
||||
|
declare -A decls |
||||
|
ttl= |
||||
|
if [[ "$key" == *" "* ]]; then |
||||
|
ttl=${key#* } |
||||
|
key=${key%% *} |
||||
|
fi |
||||
|
case "$key" in |
||||
|
"\$"*) |
||||
|
case "$key" in |
||||
|
"\$ttl") |
||||
|
bind:check:is_time ttl "$subcfg" || return 1 |
||||
|
;; |
||||
|
*) |
||||
|
echo "Unsupported variable '${key}'." >&2 |
||||
|
return 1 |
||||
|
esac |
||||
|
decls[vars]+="${key^^} $subcfg"$'\n' |
||||
|
;; |
||||
|
soa) |
||||
|
soa_values="$(printf "%-12s ; %s" "%%SERIAL%%" "serial")"$'\n' |
||||
|
for k in refresh retry expire ttl; do |
||||
|
value=$(e "$subcfg" | shyaml get-value "$k" 2>/dev/null) || { |
||||
|
err "Couldn't find any value for '$k' in '${domain}''s 'soa' config." |
||||
|
return 1 |
||||
|
} |
||||
|
bind:check:is_time "soa.$k" "$value" || { |
||||
|
err "Error while reading soa definition of domain '$domain'." |
||||
|
return 1 |
||||
|
} |
||||
|
soa_values+="$(printf "%-12s ; %s" "$value" "$k")"$'\n' |
||||
|
done |
||||
|
email=$(e "$subcfg" | shyaml get-value "email" 2>/dev/null) || { |
||||
|
err "Couldn't find any value for 'email' in '${domain}''s 'soa' config." |
||||
|
return 1 |
||||
|
} |
||||
|
soa_values="$(e "$soa_values" | prefix " ")" |
||||
|
decls[soa]+="$(printf "%-28s IN SOA %s. %s. (" "@" "${domain}" "${email/@/.}")"$'\n' |
||||
|
decls[soa]+="${soa_values}"$'\n'")"$'\n' |
||||
|
|
||||
|
;; |
||||
|
ns|mx|name|spf|txt) |
||||
|
while read-0 name name_cfg; do |
||||
|
if ! [[ "$name" =~ ^[a-z0-9_\(\),.-]+$ ]]; then |
||||
|
err "Invalid name '$name' in ${domain}'s $key records." |
||||
|
return 1 |
||||
|
fi |
||||
|
names=() |
||||
|
bind:parse:expand-in "$name" names "$vars_cfg" || return 1 |
||||
|
## values |
||||
|
vtype=$(e "$name_cfg" | shyaml get-type) |
||||
|
# echo TYPE: $vtype >&2 |
||||
|
values=() |
||||
|
case "$vtype" in |
||||
|
"sequence") |
||||
|
array_read-0 values < <(e "$name_cfg" | shyaml get-values-0) |
||||
|
;; |
||||
|
"str") |
||||
|
values=("$(e "$name_cfg" | shyaml get-value)") |
||||
|
;; |
||||
|
*) |
||||
|
err "Unsupported type '$vtype' of '$key' in $domain's zone definition." |
||||
|
exit 1 |
||||
|
;; |
||||
|
esac |
||||
|
values_expanded=() |
||||
|
for value in "${values[@]}"; do |
||||
|
case "$key" in |
||||
|
ns|name) |
||||
|
if ! [[ "$value" =~ ^[a-z0-9_\$\(\),.-]+$ ]]; then |
||||
|
err "Invalid value '$value' in ${domain}'s $key records for '$name'." |
||||
|
return 1 |
||||
|
fi |
||||
|
## Append in values_expanded |
||||
|
bind:parse:expand-in "$value" values_expanded "$vars_cfg" || return 1 |
||||
|
;; |
||||
|
mx) |
||||
|
## space is allowed (actually mandatory) |
||||
|
if ! [[ "$value" =~ ^[a-z0-9_\$\(\),.\ -]+$ ]]; then |
||||
|
err "Invalid value '$value' in ${domain}'s $key records for '$name'." |
||||
|
return 1 |
||||
|
fi |
||||
|
## Append in values_expanded |
||||
|
bind:parse:expand-in "$value" values_expanded "$vars_cfg" || return 1 |
||||
|
;; |
||||
|
spf|txt) |
||||
|
## No expansion for them |
||||
|
values_expanded+=("\"$value\"") |
||||
|
;; |
||||
|
esac |
||||
|
done |
||||
|
|
||||
|
for name in "${names[@]}"; do |
||||
|
[ "$name" == "_" ] && name="@" |
||||
|
|
||||
|
for value in "${values_expanded[@]}"; do |
||||
|
rkey="$key" |
||||
|
if [ "$key" == "name" ]; then |
||||
|
if [[ "$value" =~ ^([0-9]{1,3}\.){3,3}[0-9]{1,3}$ ]]; then |
||||
|
rkey="a" |
||||
|
elif [[ "$value" =~ ^([a-z0-9-]+\.?)+$ ]]; then |
||||
|
rkey="cname" |
||||
|
elif [ -z "$value" ]; then |
||||
|
err "Empty value for 'name' '$name', was '${values[@]}' before evaluation" |
||||
|
echo " in '$domain' zone definition." >&2 |
||||
|
return 1 |
||||
|
else |
||||
|
err "Unrecognised value for 'name': '$value'." |
||||
|
echo " in '$domain' zone definition." >&2 |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
if [ -z "$value" ]; then |
||||
|
err "Empty value for 'name' '$name'." |
||||
|
echo " in '$domain' zone definition." >&2 |
||||
|
return 1 |
||||
|
fi |
||||
|
decls[$rkey]+=$(printf "%-15s %-12s IN %s %s" "$name" "$ttl" "${rkey^^}" "$value")$'\n' |
||||
|
done |
||||
|
done |
||||
|
done < <(e "$subcfg" | shyaml key-values-0) |
||||
|
;; |
||||
|
*) |
||||
|
err "Unknown keyword '$key' in '$domain' zone definition." |
||||
|
return 1 |
||||
|
esac |
||||
|
done < <(e "$zone_cfg" | shyaml key-values-0) |
||||
|
for k in vars soa ns mx a cname spf txt; do |
||||
|
[ -z "${decls[$k]}" ] && continue |
||||
|
if [ "$k" != "vars" ]; then |
||||
|
echo |
||||
|
echo |
||||
|
echo ";; $k" |
||||
|
echo |
||||
|
fi |
||||
|
echo "${decls[$k]}" | grep -v "^$" | { |
||||
|
case "$k" in |
||||
|
a|ns|cname|spf|txt|vars) |
||||
|
sort |
||||
|
;; |
||||
|
soa|mx) |
||||
|
cat |
||||
|
;; |
||||
|
esac |
||||
|
} |
||||
|
done | tee "$cache_file" |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
name: bind |
||||
|
summary: "BIND v9 Domain Name Server" |
||||
|
maintainer: "Valentin Lab <valentin.lab@kalysto.org>" |
||||
|
inherit: base-0k |
||||
|
description: | |
||||
|
Installs a Domain Name Server. |
||||
|
config-resources: |
||||
|
- /etc/bind |
||||
|
data-resources: |
||||
|
- /var/log/bind |
||||
|
- /var/cache/bind |
||||
|
|
||||
|
|
||||
|
uses: |
||||
|
log-rotate: |
||||
|
#constraint: required | recommended | optional |
||||
|
#auto: pair | summon | none ## default: pair |
||||
|
constraint: recommended |
||||
|
auto: pair |
||||
|
solves: |
||||
|
unmanaged-logs: "in docker logs" |
||||
|
#default-options: |
||||
|
backup: |
||||
|
constraint: recommended |
||||
|
auto: pair |
||||
|
solves: |
||||
|
backup: "Automatic regular backup" |
@ -0,0 +1,12 @@ |
|||||
|
; |
||||
|
; BIND reverse data file for broadcast zone |
||||
|
; |
||||
|
$TTL 604800 |
||||
|
@ IN SOA localhost. root.localhost. ( |
||||
|
1 ; Serial |
||||
|
604800 ; Refresh |
||||
|
86400 ; Retry |
||||
|
2419200 ; Expire |
||||
|
604800 ) ; Negative Cache TTL |
||||
|
; |
||||
|
@ IN NS localhost. |
@ -0,0 +1,13 @@ |
|||||
|
; |
||||
|
; BIND reverse data file for local loopback interface |
||||
|
; |
||||
|
$TTL 604800 |
||||
|
@ IN SOA localhost. root.localhost. ( |
||||
|
1 ; Serial |
||||
|
604800 ; Refresh |
||||
|
86400 ; Retry |
||||
|
2419200 ; Expire |
||||
|
604800 ) ; Negative Cache TTL |
||||
|
; |
||||
|
@ IN NS localhost. |
||||
|
1.0.0 IN PTR localhost. |
@ -0,0 +1,12 @@ |
|||||
|
; |
||||
|
; BIND reverse data file for broadcast zone |
||||
|
; |
||||
|
$TTL 604800 |
||||
|
@ IN SOA localhost. root.localhost. ( |
||||
|
1 ; Serial |
||||
|
604800 ; Refresh |
||||
|
86400 ; Retry |
||||
|
2419200 ; Expire |
||||
|
604800 ) ; Negative Cache TTL |
||||
|
; |
||||
|
@ IN NS localhost. |
@ -0,0 +1,14 @@ |
|||||
|
; BIND reverse data file for empty rfc1918 zone |
||||
|
; |
||||
|
; DO NOT EDIT THIS FILE - it is used for multiple zones. |
||||
|
; Instead, copy it, edit named.conf, and use that copy. |
||||
|
; |
||||
|
$TTL 86400 |
||||
|
@ IN SOA localhost. root.localhost. ( |
||||
|
1 ; Serial |
||||
|
604800 ; Refresh |
||||
|
86400 ; Retry |
||||
|
2419200 ; Expire |
||||
|
86400 ) ; Negative Cache TTL |
||||
|
; |
||||
|
@ IN NS localhost. |
@ -0,0 +1,14 @@ |
|||||
|
; |
||||
|
; BIND data file for local loopback interface |
||||
|
; |
||||
|
$TTL 604800 |
||||
|
@ IN SOA localhost. root.localhost. ( |
||||
|
2 ; Serial |
||||
|
604800 ; Refresh |
||||
|
86400 ; Retry |
||||
|
2419200 ; Expire |
||||
|
604800 ) ; Negative Cache TTL |
||||
|
; |
||||
|
@ IN NS localhost. |
||||
|
@ IN A 127.0.0.1 |
||||
|
@ IN AAAA ::1 |
@ -0,0 +1,88 @@ |
|||||
|
; This file holds the information on root name servers needed to |
||||
|
; initialize cache of Internet domain name servers |
||||
|
; (e.g. reference this file in the "cache . <file>" |
||||
|
; configuration file of BIND domain name servers). |
||||
|
; |
||||
|
; This file is made available by InterNIC |
||||
|
; under anonymous FTP as |
||||
|
; file /domain/named.cache |
||||
|
; on server FTP.INTERNIC.NET |
||||
|
; -OR- RS.INTERNIC.NET |
||||
|
; |
||||
|
; last update: Jan 3, 2013 |
||||
|
; related version of root zone: 2013010300 |
||||
|
; |
||||
|
; formerly NS.INTERNIC.NET |
||||
|
; |
||||
|
. 3600000 IN NS A.ROOT-SERVERS.NET. |
||||
|
A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 |
||||
|
A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30 |
||||
|
; |
||||
|
; FORMERLY NS1.ISI.EDU |
||||
|
; |
||||
|
. 3600000 NS B.ROOT-SERVERS.NET. |
||||
|
B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201 |
||||
|
; |
||||
|
; FORMERLY C.PSI.NET |
||||
|
; |
||||
|
. 3600000 NS C.ROOT-SERVERS.NET. |
||||
|
C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12 |
||||
|
; |
||||
|
; FORMERLY TERP.UMD.EDU |
||||
|
; |
||||
|
. 3600000 NS D.ROOT-SERVERS.NET. |
||||
|
D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13 |
||||
|
D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2D::D |
||||
|
; |
||||
|
; FORMERLY NS.NASA.GOV |
||||
|
; |
||||
|
. 3600000 NS E.ROOT-SERVERS.NET. |
||||
|
E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10 |
||||
|
; |
||||
|
; FORMERLY NS.ISC.ORG |
||||
|
; |
||||
|
. 3600000 NS F.ROOT-SERVERS.NET. |
||||
|
F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241 |
||||
|
F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2F::F |
||||
|
; |
||||
|
; FORMERLY NS.NIC.DDN.MIL |
||||
|
; |
||||
|
. 3600000 NS G.ROOT-SERVERS.NET. |
||||
|
G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4 |
||||
|
; |
||||
|
; FORMERLY AOS.ARL.ARMY.MIL |
||||
|
; |
||||
|
. 3600000 NS H.ROOT-SERVERS.NET. |
||||
|
H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53 |
||||
|
H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803F:235 |
||||
|
; |
||||
|
; FORMERLY NIC.NORDU.NET |
||||
|
; |
||||
|
. 3600000 NS I.ROOT-SERVERS.NET. |
||||
|
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17 |
||||
|
I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FE::53 |
||||
|
; |
||||
|
; OPERATED BY VERISIGN, INC. |
||||
|
; |
||||
|
. 3600000 NS J.ROOT-SERVERS.NET. |
||||
|
J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30 |
||||
|
J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30 |
||||
|
; |
||||
|
; OPERATED BY RIPE NCC |
||||
|
; |
||||
|
. 3600000 NS K.ROOT-SERVERS.NET. |
||||
|
K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 |
||||
|
K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FD::1 |
||||
|
; |
||||
|
; OPERATED BY ICANN |
||||
|
; |
||||
|
. 3600000 NS L.ROOT-SERVERS.NET. |
||||
|
L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42 |
||||
|
L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:3::42 |
||||
|
; |
||||
|
; OPERATED BY WIDE |
||||
|
; |
||||
|
. 3600000 NS M.ROOT-SERVERS.NET. |
||||
|
M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33 |
||||
|
M.ROOT-SERVERS.NET. 3600000 AAAA 2001:DC3::35 |
||||
|
; End of File |
@ -0,0 +1,3 @@ |
|||||
|
include "/etc/bind/named.conf.options"; |
||||
|
include "/etc/bind/named.conf.local"; |
||||
|
include "/etc/bind/named.conf.default-zones"; |
@ -0,0 +1,30 @@ |
|||||
|
// prime the server with knowledge of the root servers |
||||
|
zone "." { |
||||
|
type hint; |
||||
|
file "/etc/bind/db.root"; |
||||
|
}; |
||||
|
|
||||
|
// be authoritative for the localhost forward and reverse zones, and for |
||||
|
// broadcast zones as per RFC 1912 |
||||
|
|
||||
|
zone "localhost" { |
||||
|
type master; |
||||
|
file "/etc/bind/db.local"; |
||||
|
}; |
||||
|
|
||||
|
zone "127.in-addr.arpa" { |
||||
|
type master; |
||||
|
file "/etc/bind/db.127"; |
||||
|
}; |
||||
|
|
||||
|
zone "0.in-addr.arpa" { |
||||
|
type master; |
||||
|
file "/etc/bind/db.0"; |
||||
|
}; |
||||
|
|
||||
|
zone "255.in-addr.arpa" { |
||||
|
type master; |
||||
|
file "/etc/bind/db.255"; |
||||
|
}; |
||||
|
|
||||
|
|
@ -0,0 +1,56 @@ |
|||||
|
options { |
||||
|
directory "/var/cache/bind"; |
||||
|
|
||||
|
// If there is a firewall between you and nameservers you want |
||||
|
// to talk to, you may need to fix the firewall to allow multiple |
||||
|
// ports to talk. See http://www.kb.cert.org/vuls/id/800113 |
||||
|
|
||||
|
// If your ISP provided one or more IP addresses for stable |
||||
|
// nameservers, you probably want to use them as forwarders. |
||||
|
// Uncomment the following block, and insert the addresses replacing |
||||
|
// the all-0's placeholder. |
||||
|
|
||||
|
// forwarders { |
||||
|
// 0.0.0.0; |
||||
|
// }; |
||||
|
|
||||
|
//======================================================================== |
||||
|
// If BIND logs error messages about the root key being expired, |
||||
|
// you will need to update your keys. See https://www.isc.org/bind-keys |
||||
|
//======================================================================== |
||||
|
dnssec-validation auto; |
||||
|
|
||||
|
auth-nxdomain no; # conform to RFC1035 |
||||
|
// listen-on-v6 { any; }; |
||||
|
|
||||
|
// allow-recursion yes; |
||||
|
allow-recursion { 127.0.0.1; 172.210/16; 172.18/16; 51.255.66.199;}; |
||||
|
allow-recursion-on { any;}; |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
logging { |
||||
|
channel warning |
||||
|
{ |
||||
|
file "/var/log/bind/dns.warnings.log"; |
||||
|
severity warning; |
||||
|
print-category yes; |
||||
|
print-severity yes; |
||||
|
print-time yes; |
||||
|
}; |
||||
|
|
||||
|
channel general_dns |
||||
|
{ |
||||
|
file "/var/log/bind/dns.log"; |
||||
|
severity info; |
||||
|
print-category yes; |
||||
|
print-severity yes; |
||||
|
print-time yes; |
||||
|
}; |
||||
|
|
||||
|
category default { warning; } ; |
||||
|
category queries { general_dns; } ; |
||||
|
}; |
||||
|
|
@ -0,0 +1,20 @@ |
|||||
|
zone "10.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
|
||||
|
zone "16.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "17.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "18.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "19.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "20.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "21.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "22.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "23.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "24.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "25.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "26.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "27.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "28.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "29.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "30.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
zone "31.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
||||
|
|
||||
|
zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue