├── README.md ├── hosts ├── idc2-bind-master.yml ├── library └── heylinux │ └── myfacts └── roles └── bind ├── files └── idc2 │ └── named │ ├── Kheylinux.com.+157+59510.key │ ├── Kheylinux.com.+157+59510.private │ └── heylinux.com.key ├── tasks ├── base.yml ├── main.yml └── update.yml ├── templates └── idc2 │ ├── 8.16.172.in-addr.arpa.zone.j2 │ ├── heylinux.com.zone.j2 │ └── named.conf.j2 └── vars ├── 8.16.172.in-addr.arpa.yml ├── A.yml ├── CNAME.yml ├── dns_ops.sh ├── zones_all.yml ├── zones_rvs.yml └── zones_std.yml /README.md: -------------------------------------------------------------------------------- 1 | ## Setup and manage BIND9 zone files with Ansible 2 | 3 | ### Method: 4 | 5 | ``` 6 | 1. Use a customized module `myfacts` to get the serial number 7 | 2. Use a shell script `dns_ops.sh` to add|delete DNS records 8 | 3. Use YAML vars files to store the DNS records 9 | 4. Use templates files to get DNS records then update the zone files 10 | ``` 11 | 12 | ### Here is the script `dns_ops.sh`: 13 | 14 | ``` 15 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh 16 | Examples: 17 | roles/bind/vars/dns_ops.sh -t A -u add -n ns1 -v 172.16.8.246 18 | roles/bind/vars/dns_ops.sh -t A -u del -n ns1 -v 172.16.8.246 19 | roles/bind/vars/dns_ops.sh -t CNAME -u add -n ns3 -v ns1.heylinux.com 20 | roles/bind/vars/dns_ops.sh -t CNAME -u del -n ns3 -v ns1.heylinux.com 21 | roles/bind/vars/dns_ops.sh -t PTR -u add -n 172.16.8.246 -v ns1.heylinux.com 22 | roles/bind/vars/dns_ops.sh -t PTR -u del -n 172.16.8.246 -v ns1.heylinux.com 23 | ``` 24 | 25 | ### Here are some practices: 26 | 27 | #### Check if the name contain the top level domain: 28 | 29 | ``` 30 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t A -u add -n ns6.heylinux.com -v 172.16.8.251 31 | 'ns6.heylinux.com' is malformed. Servername should be just 'ns6' without the 'heylinux.com' 32 | ``` 33 | 34 | #### Check the duplicate record: 35 | 36 | ``` 37 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t A -u add -n ns6 -v 172.16.8.251 38 | Failed because duplicate record: 'ns6: 172.16.8.253' 39 | ``` 40 | 41 | #### Check if the value doesnt match: 42 | 43 | ``` 44 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t A -u del -n ns6 -v 172.16.8.251 45 | Failed because the existing record's value doesnt match: 'ns6: 172.16.8.253' 46 | ``` 47 | 48 | #### Delete a record: 49 | 50 | ``` 51 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t A -u del -n ns6 -v 172.16.8.253 52 | Updated A records in A.yml: delete 'ns6: 172.16.8.253' 53 | You may need to push via Ansible to update the records on DNS Servers 54 | ``` 55 | 56 | #### Add a record: 57 | 58 | ``` 59 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t A -u add -n ns6 -v 172.16.8.251 60 | Updated A records in A.yml: add 'ns6: 172.16.8.251' 61 | You may need to push via Ansible to update the records on DNS Servers 62 | ``` 63 | 64 | #### View the YAML data file which just updated by the script dns_ops.sh: 65 | 66 | ``` 67 | [dong@idc2-admin1 ansible]$ cat roles/bind/vars/A.yml 68 | --- 69 | A: 70 | ns1: 172.16.8.246 71 | ns2: 172.16.8.247 72 | ns4: 172.16.8.249 73 | ns6: 172.16.8.251 74 | 75 | [dong@idc2-admin1 ansible]$ cat roles/bind/vars/CNAME.yml 76 | --- 77 | CNAME: 78 | www: heylinux.com 79 | mail: exmail.qq.com 80 | ns3: ns1.heylinux.com 81 | ``` 82 | 83 | #### Add a CNAME record: 84 | 85 | ``` 86 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t CNAME -u add -n ns7 -v ns6.heylinux.com 87 | Updated CNAME records in CNAME.yml: add 'ns7: ns6.heylinux.com' 88 | You may need to push via Ansible to update the records on DNS Servers 89 | ``` 90 | 91 | #### View the YAML data file which just updated by the script dns_ops.sh: 92 | 93 | ``` 94 | [dong@idc2-admin1 ansible]$ cat roles/bind/vars/CNAME.yml 95 | --- 96 | CNAME: 97 | www: heylinux.com 98 | mail: exmail.qq.com 99 | ns3: ns1.heylinux.com 100 | ns7: ns6.heylinux.com 101 | ``` 102 | 103 | #### Check if give wrong IP address or the sub network doesnt exist: 104 | 105 | ``` 106 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t PTR -u add -n ns6 -v 172.16.8.251 107 | 'ns6' is malformed. Should be a IP address 108 | 109 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t PTR -u add -n 172.168.8.251 -v ns6.heylinux.com 110 | 8.168.172.in-addr.arpa.yml does not exist 111 | ``` 112 | 113 | #### Add a PTR record: 114 | 115 | ``` 116 | [dong@idc2-admin1 ansible]$ roles/bind/vars/dns_ops.sh -t PTR -u add -n 172.16.8.251 -v ns6.heylinux.com 117 | Updated PTR records in 8.16.172.in-addr.arpa.yml: add '251: ns6.heylinux.com' 118 | You may need to push via Ansible to update the records on DNS Servers 119 | ``` 120 | 121 | #### View the YAML data file which just updated by the script dns_ops.sh: 122 | 123 | ``` 124 | [dong@idc2-admin1 ansible]$ cat roles/bind/vars/8.16.172.in-addr.arpa.yml 125 | --- 126 | ptr_8_16_172: 127 | 247: ns2.heylinux.com 128 | 249: ns4.heylinux.com 129 | 246: ns1.heylinux.com 130 | 251: ns6.heylinux.com 131 | ``` 132 | 133 | ### Then we can `Push the New Records` to DNS masters: 134 | 135 | ``` 136 | [dong@idc2-admin1 ansible]$ ansible-playbook idc2-bind-master.yml -i hosts -u root -k --tags bind-update 137 | PLAY [bind-master] ************************************************************ 138 | 139 | GATHERING FACTS *************************************************************** 140 | ok: [idc2-dong1] 141 | 142 | TASK: [bind | get zones and A,CNAME records] ********************************** 143 | ok: [idc2-dong1] => (item=zones_all.yml) 144 | ok: [idc2-dong1] => (item=zones_std.yml) 145 | ok: [idc2-dong1] => (item=zones_rvs.yml) 146 | ok: [idc2-dong1] => (item=A.yml) 147 | ok: [idc2-dong1] => (item=CNAME.yml) 148 | 149 | TASK: [bind | get PTR records] ************************************************ 150 | ok: [idc2-dong1] => (item={'domain': '8.16.172.in-addr.arpa', 'file': '8.16.172.in-addr.arpa.zone'}) 151 | 152 | TASK: [bind | get ansible_dns_new_serial_number of all zones] ***************** 153 | ok: [idc2-dong1] 154 | 155 | TASK: [bind | create zones configuration files] ******************************* 156 | changed: [idc2-dong1] => (item={'domain': 'heylinux.com', 'file': 'heylinux.com.zone'}) 157 | 158 | TASK: [bind | create reverse zones configuration files] *********************** 159 | changed: [idc2-dong1] => (item={'domain': '8.16.172.in-addr.arpa', 'file': '8.16.172.in-addr.arpa.zone'}) 160 | 161 | TASK: [bind | reload rndc service to load new records] ************************ 162 | changed: [idc2-dong1] 163 | 164 | PLAY RECAP ******************************************************************** 165 | idc2-dong1 : ok=7 changed=3 unreachable=0 failed=0 166 | ``` 167 | 168 | ### Check if the Records Updated on DNS masters: 169 | 170 | ``` 171 | [root@idc2-dong1 named]# host ns6 172 | ns6.heylinux.com has address 172.16.8.251 173 | 174 | [root@idc2-dong1 named]# host ns7 175 | ns7.heylinux.com is an alias for ns6.heylinux.com. 176 | ns6.heylinux.com has address 172.16.8.251 177 | 178 | [root@idc2-dong1 named]# host 172.16.8.251 179 | 251.8.16.172.in-addr.arpa domain name pointer ns6.heylinux.com. 180 | ``` 181 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | [bind-master] 2 | idc2-dong1 3 | -------------------------------------------------------------------------------- /idc2-bind-master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: bind-master 3 | vars: 4 | colo: idc2 5 | roles: 6 | - bind 7 | -------------------------------------------------------------------------------- /library/heylinux/myfacts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import json 4 | import commands 5 | import re 6 | 7 | def get_ansible_dns_new_serial_number(domain_name): 8 | serial_number = commands.getoutput("""dig soa %s |grep -A1 'ANSWER SECTION' |tail -n 1 |awk '{print $7}'""" % (domain_name)) 9 | ansible_dns_new_serial_number = int(serial_number) + 1 10 | return ansible_dns_new_serial_number 11 | 12 | def main(): 13 | global module 14 | module = AnsibleModule( 15 | argument_spec = dict( 16 | get_facts=dict(default="yes", required=False), 17 | domain_names=dict(required=False), 18 | ), 19 | supports_check_mode = True, 20 | ) 21 | 22 | ansible_facts_dict = { 23 | "changed" : False, 24 | "ansible_facts": { 25 | "ansible_dns_new_serial_number": {} 26 | } 27 | } 28 | 29 | if module.params['get_facts'] == 'yes': 30 | if module.params['domain_names']: 31 | domain_names_list = module.params['domain_names'].split(",") 32 | for domain_name in domain_names_list: 33 | ansible_dns_new_serial_number = get_ansible_dns_new_serial_number(domain_name) 34 | ansible_facts_dict['ansible_facts']['ansible_dns_new_serial_number'][domain_name] = ansible_dns_new_serial_number 35 | 36 | print json.dumps(ansible_facts_dict) 37 | 38 | from ansible.module_utils.basic import * 39 | from ansible.module_utils.facts import * 40 | main() 41 | -------------------------------------------------------------------------------- /roles/bind/files/idc2/named/Kheylinux.com.+157+59510.key: -------------------------------------------------------------------------------- 1 | heylinux.com. IN KEY 0 3 157 4Cn0wwI+STjsW+3S5dEEdQ== 2 | -------------------------------------------------------------------------------- /roles/bind/files/idc2/named/Kheylinux.com.+157+59510.private: -------------------------------------------------------------------------------- 1 | Private-key-format: v1.3 2 | Algorithm: 157 (HMAC_MD5) 3 | Key: 4Cn0wwI+STjsW+3S5dEEdQ== 4 | Bits: AAA= 5 | Created: 20140918125817 6 | Publish: 20140918125817 7 | Activate: 20140918125817 8 | -------------------------------------------------------------------------------- /roles/bind/files/idc2/named/heylinux.com.key: -------------------------------------------------------------------------------- 1 | key "heylinux.com." { 2 | algorithm hmac-md5; 3 | secret "4Cn0wwI+STjsW+3S5dEEdQ=="; 4 | }; 5 | -------------------------------------------------------------------------------- /roles/bind/tasks/base.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install needed rpm packages 3 | yum: name={{ item }} state=present 4 | with_items: 5 | - bind 6 | - bind-devel 7 | - bind-libs 8 | - bind-utils 9 | - bind-chroot 10 | tags: 11 | - bind 12 | - bind-base 13 | 14 | - name: create dirs for logs 15 | file: path={{ item }} state=directory owner=named group=named mode=0755 16 | with_items: 17 | - /var/named/chroot/var/log/named 18 | tags: 19 | - bind 20 | - bind-base 21 | 22 | - name: create files for logs 23 | shell: creates=/var/named/chroot/var/log/named/{{ item }} touch /var/named/chroot/var/log/named/{{ item }} 24 | with_items: 25 | - client.log 26 | - config.log 27 | - database.log 28 | - default.log 29 | - dispatch.log 30 | - dnssec.log 31 | - general.log 32 | - lame-servers.log 33 | - network.log 34 | - notify.log 35 | - queries.log 36 | - resolver.log 37 | - security.log 38 | - unmatched.log 39 | - update.log 40 | - xfer-in.log 41 | - xfer-out.log 42 | tags: 43 | - bind 44 | - bind-base 45 | 46 | - name: create files for logs 47 | file: path=/var/named/chroot/var/log/named/{{ item }} owner=named group=named mode=0644 48 | with_items: 49 | - client.log 50 | - config.log 51 | - database.log 52 | - default.log 53 | - dispatch.log 54 | - dnssec.log 55 | - general.log 56 | - lame-servers.log 57 | - network.log 58 | - notify.log 59 | - queries.log 60 | - resolver.log 61 | - security.log 62 | - unmatched.log 63 | - update.log 64 | - xfer-in.log 65 | - xfer-out.log 66 | tags: 67 | - bind 68 | - bind-base 69 | 70 | - name: update attributes for /var/named 71 | file: path={{ item }} state=directory owner=named group=named mode=0750 72 | with_items: 73 | - /var/named 74 | tags: 75 | - bind 76 | - bind-base 77 | 78 | - name: create named.conf configuration file 79 | template: src={{ colo }}/named.conf.j2 dest=/etc/named.conf owner=root group=named mode=0640 80 | tags: 81 | - bind 82 | - bind-base 83 | 84 | - name: create key configuration file 85 | copy: src={{ colo }}/named/{{ item }} dest=/var/named/{{ item }} owner=named group=named mode=0640 86 | with_items: 87 | - heylinux.com.key 88 | tags: 89 | - bind 90 | - bind-base 91 | 92 | - name: create key files 93 | copy: src={{ colo }}/named/{{ item }} dest=/var/named/{{ item }} owner=named group=named mode=0600 94 | with_items: 95 | - Kheylinux.com.+157+59510.key 96 | - Kheylinux.com.+157+59510.private 97 | tags: 98 | - bind 99 | - bind-base 100 | -------------------------------------------------------------------------------- /roles/bind/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: base.yml 3 | - include: update.yml 4 | -------------------------------------------------------------------------------- /roles/bind/tasks/update.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: get zones and A,CNAME records 3 | include_vars: "{{ item }}" 4 | with_items: 5 | - "zones_all.yml" 6 | - "zones_std.yml" 7 | - "zones_rvs.yml" 8 | - "A.yml" 9 | - "CNAME.yml" 10 | tags: 11 | - bind 12 | - bind-update 13 | 14 | - name: get PTR records 15 | include_vars: "{{ item.domain }}.yml" 16 | with_items: 17 | - "{{ reverse_zones }}" 18 | tags: 19 | - bind 20 | - bind-update 21 | 22 | - name: get ansible_dns_new_serial_number of all zones 23 | myfacts: get_facts=yes domain_names={{ all_zones_list|join(',') }} 24 | tags: 25 | - bind 26 | - bind-update 27 | 28 | - name: create zones configuration files 29 | template: src={{ colo }}/{{ item.file }}.j2 dest=/var/named/{{ item.file }} owner=named group=named mode=0644 30 | with_items: 31 | - "{{ standard_zones }}" 32 | tags: 33 | - bind 34 | - bind-update 35 | 36 | - name: create reverse zones configuration files 37 | template: src={{ colo }}/{{ item.file }}.j2 dest=/var/named/{{ item.file }} owner=named group=named mode=0644 38 | with_items: 39 | - "{{ reverse_zones }}" 40 | tags: 41 | - bind 42 | - bind-update 43 | 44 | - name: reload rndc service to load new records 45 | shell: rndc freeze && rndc reload && rndc thaw 46 | tags: 47 | - bind 48 | - bind-update 49 | -------------------------------------------------------------------------------- /roles/bind/templates/idc2/8.16.172.in-addr.arpa.zone.j2: -------------------------------------------------------------------------------- 1 | ;{{ ansible_managed }} 2 | $ORIGIN . 3 | $TTL 86400 ; 1 day 4 | 8.16.172.in-addr.arpa IN SOA ns1.heylinux.com. root.heylinux.com. ( 5 | {{ ansible_dns_new_serial_number['8.16.172.in-addr.arpa'] }} ; serial 6 | 3600 ; refresh (1 hour) 7 | 60 ; retry (1 minute) 8 | 604800 ; expire (1 week) 9 | 3600 ; minimum (1 hour) 10 | ) 11 | NS ns1.heylinux.com. 12 | A 255.255.255.0 13 | PTR heylinux.com. 14 | $ORIGIN 8.16.172.in-addr.arpa. 15 | {% for name, addr in ptr_8_16_172.iteritems() %} 16 | {{ name }} PTR {{ addr }} 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /roles/bind/templates/idc2/heylinux.com.zone.j2: -------------------------------------------------------------------------------- 1 | ;{{ ansible_managed }} 2 | $ORIGIN . 3 | $TTL 86400 ; 1 day 4 | heylinux.com IN SOA ns1.heylinux.com. root.heylinux.com. ( 5 | {{ ansible_dns_new_serial_number['heylinux.com'] }} ; serial 6 | 300 ; refresh (5 minutes) 7 | 60 ; retry (1 minute) 8 | 604800 ; expire (1 week) 9 | 3600 ; minimum (1 hour) 10 | ) 11 | NS ns1.heylinux.com. 12 | NS ns2.heylinux.com. 13 | A 54.238.131.140 14 | MX 5 mxbiz1.qq.com. 15 | MX 10 mxbiz2.qq.com. 16 | $ORIGIN heylinux.com. 17 | {% for name, addr in A.iteritems() %} 18 | {{ name }} A {{ addr }} 19 | {% endfor %} 20 | {% for name, addr in CNAME.iteritems() %} 21 | {{ name }} CNAME {{ addr }}. 22 | {% endfor %} 23 | -------------------------------------------------------------------------------- /roles/bind/templates/idc2/named.conf.j2: -------------------------------------------------------------------------------- 1 | // 2 | // named.conf 3 | // 4 | // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS 5 | // server as a caching only nameserver (as a localhost DNS resolver only). 6 | // 7 | // See /usr/share/doc/bind*/sample/ for example named configuration files. 8 | // 9 | 10 | include "/etc/rndc.key"; 11 | include "/var/named/heylinux.com.key"; 12 | 13 | controls { 14 | inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; }; 15 | }; 16 | 17 | acl slave_servers { 172.16.8.247; }; 18 | 19 | options { 20 | #listen-on port 53 { 127.0.0.1; }; 21 | #listen-on-v6 port 53 { ::1; }; 22 | listen-on-v6 { none; }; 23 | directory "/var/named"; 24 | dump-file "/var/named/data/cache_dump.db"; 25 | statistics-file "/var/named/data/named_stats.txt"; 26 | memstatistics-file "/var/named/data/named_mem_stats.txt"; 27 | allow-query { any; }; 28 | allow-transfer { slave_servers; }; 29 | also-notify { 172.16.8.247; }; 30 | recursion yes; 31 | 32 | dnssec-enable yes; 33 | dnssec-validation yes; 34 | dnssec-lookaside auto; 35 | 36 | /* Path to ISC DLV key */ 37 | bindkeys-file "/etc/named.iscdlv.key"; 38 | 39 | managed-keys-directory "/var/named/dynamic"; 40 | }; 41 | 42 | logging { 43 | channel default_file { file "/var/log/named/default.log" versions 3 size 5m; severity dynamic; print-time yes; }; 44 | channel general_file { file "/var/log/named/general.log" versions 3 size 5m; severity dynamic; print-time yes; }; 45 | channel database_file { file "/var/log/named/database.log" versions 3 size 5m; severity dynamic; print-time yes; }; 46 | channel security_file { file "/var/log/named/security.log" versions 3 size 5m; severity dynamic; print-time yes; }; 47 | channel config_file { file "/var/log/named/config.log" versions 3 size 5m; severity dynamic; print-time yes; }; 48 | channel resolver_file { file "/var/log/named/resolver.log" versions 3 size 5m; severity dynamic; print-time yes; }; 49 | channel xfer-in_file { file "/var/log/named/xfer-in.log" versions 3 size 5m; severity dynamic; print-time yes; }; 50 | channel xfer-out_file { file "/var/log/named/xfer-out.log" versions 3 size 5m; severity dynamic; print-time yes; }; 51 | channel notify_file { file "/var/log/named/notify.log" versions 3 size 5m; severity dynamic; print-time yes; }; 52 | channel client_file { file "/var/log/named/client.log" versions 3 size 5m; severity dynamic; print-time yes; }; 53 | channel unmatched_file { file "/var/log/named/unmatched.log" versions 3 size 5m; severity dynamic; print-time yes; }; 54 | channel queries_file { file "/var/log/named/queries.log" versions 3 size 5m; severity dynamic; print-time yes; }; 55 | channel network_file { file "/var/log/named/network.log" versions 3 size 5m; severity dynamic; print-time yes; }; 56 | channel update_file { file "/var/log/named/update.log" versions 3 size 5m; severity dynamic; print-time yes; }; 57 | channel dispatch_file { file "/var/log/named/dispatch.log" versions 3 size 5m; severity dynamic; print-time yes; }; 58 | channel dnssec_file { file "/var/log/named/dnssec.log" versions 3 size 5m; severity dynamic; print-time yes; }; 59 | channel lame-servers_file { file "/var/log/named/lame-servers.log" versions 3 size 5m; severity dynamic; print-time yes; }; 60 | 61 | category default { default_file; }; 62 | category general { general_file; }; 63 | category database { database_file; }; 64 | category security { security_file; }; 65 | category config { config_file; }; 66 | category resolver { resolver_file; }; 67 | category xfer-in { xfer-in_file; }; 68 | category xfer-out { xfer-out_file; }; 69 | category notify { notify_file; }; 70 | category client { client_file; }; 71 | category unmatched { unmatched_file; }; 72 | category queries { queries_file; }; 73 | category network { network_file; }; 74 | category update { update_file; }; 75 | category dispatch { dispatch_file; }; 76 | category dnssec { dnssec_file; }; 77 | category lame-servers { lame-servers_file; }; 78 | }; 79 | 80 | view "internal_resolver" { 81 | match-clients { 82 | localhost; 83 | 172.16.8.0/24; 84 | }; 85 | 86 | zone "." IN { 87 | type hint; 88 | file "named.ca"; 89 | }; 90 | 91 | zone "heylinux.com" IN { 92 | type master; 93 | file "heylinux.com.zone"; 94 | allow-update { key "heylinux.com."; }; 95 | }; 96 | 97 | zone "8.16.172.in-addr.arpa" IN { 98 | type master; 99 | file "8.16.172.in-addr.arpa.zone"; 100 | allow-update { key "heylinux.com."; }; 101 | }; 102 | 103 | include "/etc/named.rfc1912.zones"; 104 | }; 105 | -------------------------------------------------------------------------------- /roles/bind/vars/8.16.172.in-addr.arpa.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ptr_8_16_172: 3 | 247: ns2.heylinux.com 4 | 249: ns4.heylinux.com 5 | 246: ns1.heylinux.com 6 | 251: ns6.heylinux.com 7 | -------------------------------------------------------------------------------- /roles/bind/vars/A.yml: -------------------------------------------------------------------------------- 1 | --- 2 | A: 3 | ns1: 172.16.8.246 4 | ns2: 172.16.8.247 5 | ns4: 172.16.8.249 6 | ns6: 172.16.8.251 7 | -------------------------------------------------------------------------------- /roles/bind/vars/CNAME.yml: -------------------------------------------------------------------------------- 1 | --- 2 | CNAME: 3 | www: heylinux.com 4 | mail: exmail.qq.com 5 | ns3: ns1.heylinux.com 6 | ns7: ns6.heylinux.com 7 | ns8: ns6.heylinux.com 8 | -------------------------------------------------------------------------------- /roles/bind/vars/dns_ops.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # DNS records management tool for YAML Files in Ansible 4 | # By Dong Guo at 20140926 5 | 6 | basedir=$(dirname ${0}) 7 | domain=heylinux.com 8 | 9 | function print_help(){ 10 | echo "Usage: ${0} -t A|CNAME|PTR -u add|del -n servername -v record_value" 11 | echo "Examples:" 12 | echo "${0} -t A -u add -n ns1 -v 172.16.8.246" 13 | echo "${0} -t A -u del -n ns1 -v 172.16.8.246" 14 | echo "${0} -t CNAME -u add -n ns3 -v ns1.heylinux.com" 15 | echo "${0} -t CNAME -u del -n ns3 -v ns1.heylinux.com" 16 | echo "${0} -t PTR -u add -n 172.16.8.246 -v ns1.heylinux.com" 17 | echo "${0} -t PTR -u del -n 172.16.8.246 -v ns1.heylinux.com" 18 | exit 1 19 | } 20 | 21 | function check_servername(){ 22 | echo $servername | grep -wq ${domain} 23 | if [[ $? -eq 0 ]]; then 24 | hostname=$(echo $servername | cut -d. -f1) 25 | echo "'${servername}' is malformed. Servername should be just '${hostname}' without the '${domain}'" 26 | exit 1 27 | fi 28 | } 29 | 30 | function check_fqdn(){ 31 | echo $record_value | grep -q '\.' 32 | if [[ $? -ne 0 ]]; then 33 | echo "'${record_value}' is malformed. Should be a FQDN" 34 | exit 1 35 | fi 36 | } 37 | 38 | function update_record(){ 39 | if [[ ${record_type} == "PTR" ]]; then 40 | filename=$domain 41 | else 42 | filename=$record_type 43 | fi 44 | if [[ $action == "add" ]]; then 45 | grep -wq "$servername:" ${basedir}/${filename}.yml 46 | if [[ $? -eq 0 ]]; then 47 | echo "Failed because duplicate record: '$(grep -w "$servername:" ${basedir}/${filename}.yml|awk '{print $1" "$2}')'" 48 | exit 1 49 | else 50 | echo " $servername: $record_value" >> ${basedir}/${filename}.yml 51 | fi 52 | fi 53 | if [[ $action == "delete" ]]; then 54 | grep -wq "$servername:" ${basedir}/${filename}.yml 55 | if [ $? -ne 0 ]; then 56 | echo "Failed because nonexistent record" 57 | exit 1 58 | else 59 | grep -w "$servername:" ${basedir}/${filename}.yml | grep -wq "${record_value}" 60 | if [[ $? -ne 0 ]]; then 61 | echo "Failed because the existing record's value doesnt match: '$(grep -w "$servername:" ${basedir}/${filename}.yml|awk '{print $1" "$2}')'" 62 | exit 1 63 | else 64 | sed -i /"${servername}: ${record_value}"/d ${basedir}/${filename}.yml 65 | fi 66 | fi 67 | fi 68 | echo "Updated ${record_type} records in ${filename}.yml: $action '$servername: $record_value'" 69 | echo "You may need to push via Ansible to update the records on DNS Servers" 70 | } 71 | 72 | while getopts "t:u:n:v:" opts 73 | do 74 | case "$opts" in 75 | "t") 76 | record_type=$OPTARG 77 | ;; 78 | "u") 79 | action=$OPTARG 80 | ;; 81 | "n") 82 | servername=$OPTARG 83 | ;; 84 | "v") 85 | record_value=$OPTARG 86 | ;; 87 | *) 88 | print_help 89 | ;; 90 | esac 91 | done 92 | 93 | if [[ -z "$record_type" ]] || [[ -z "$action" ]] || [[ -z "$servername" ]] || [[ -z "$record_value" ]]; then 94 | print_help 95 | else 96 | case "$action" in 97 | "add") 98 | action=add 99 | ;; 100 | "del") 101 | action=delete 102 | ;; 103 | *) 104 | print_help 105 | ;; 106 | esac 107 | case "$record_type" in 108 | "A") 109 | check_servername 110 | update_record 111 | ;; 112 | "CNAME") 113 | check_servername 114 | check_fqdn 115 | update_record 116 | ;; 117 | "PTR") 118 | check_fqdn 119 | a=$(echo $servername |cut -d. -f1 |grep -Ev '[a-z]|[A-Z]') 120 | b=$(echo $servername |cut -d. -f2 |grep -Ev '[a-z]|[A-Z]') 121 | c=$(echo $servername |cut -d. -f3 |grep -Ev '[a-z]|[A-Z]') 122 | d=$(echo $servername |cut -d. -f4 |grep -Ev '[a-z]|[A-Z]') 123 | if [[ -z "$a" ]] || [[ -z "$b" ]] || [[ -z "$c" ]] || [[ -z "$d" ]]; then 124 | echo "'${servername}' is malformed. Should be a IP address" 125 | else 126 | domain=$c.$b.$a.in-addr.arpa 127 | servername=$d 128 | if [[ ! -f ${basedir}/${domain}.yml ]]; then 129 | echo "${domain}.yml does not exist" 130 | exit 1 131 | else 132 | update_record 133 | fi 134 | fi 135 | ;; 136 | *) 137 | print_help 138 | ;; 139 | esac 140 | fi 141 | -------------------------------------------------------------------------------- /roles/bind/vars/zones_all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | all_zones_list: 3 | - heylinux.com 4 | - '8.16.172.in-addr.arpa' 5 | -------------------------------------------------------------------------------- /roles/bind/vars/zones_rvs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | reverse_zones: 3 | - domain: '8.16.172.in-addr.arpa' 4 | file: '8.16.172.in-addr.arpa.zone' 5 | -------------------------------------------------------------------------------- /roles/bind/vars/zones_std.yml: -------------------------------------------------------------------------------- 1 | --- 2 | standard_zones: 3 | - domain: heylinux.com 4 | file: heylinux.com.zone 5 | --------------------------------------------------------------------------------