| 1 | web frontend:
 | 
|---|
| 2 | 
 | 
|---|
| 3 | workflow:
 | 
|---|
| 4 | 
 | 
|---|
| 5 | log in, see domain list from current group
 | 
|---|
| 6 | 
 | 
|---|
| 7 | -> "current group" includes all subgroups?  (hairy SQL)
 | 
|---|
| 8 | 
 | 
|---|
| 9 | 
 | 
|---|
| 10 | logic:
 | 
|---|
| 11 | -> need to pass session ID on every call, otherwise we don't know who we are
 | 
|---|
| 12 | -> should check ACLs on every call in case of changing permissions
 | 
|---|
| 13 | -> should be able to store all webvar bits in the session
 | 
|---|
| 14 | 
 | 
|---|
| 15 | 
 | 
|---|
| 16 | ooo! ooo!  what about "clone existing domain"?
 | 
|---|
| 17 | 
 | 
|---|
| 18 | 
 | 
|---|
| 19 | components:
 | 
|---|
| 20 | menu list (actions/sections)
 | 
|---|
| 21 | domain list
 | 
|---|
| 22 | group tree
 | 
|---|
| 23 | user list
 | 
|---|
| 24 | <various edit <entity> pages>
 | 
|---|
| 25 | 
 | 
|---|
| 26 | 
 | 
|---|
| 27 | 
 | 
|---|
| 28 | time tables:
 | 
|---|
| 29 | 3600: 1h
 | 
|---|
| 30 | 7200: 2h
 | 
|---|
| 31 | 10800: 3h
 | 
|---|
| 32 | 14400: 4h
 | 
|---|
| 33 | 21600: 6h
 | 
|---|
| 34 | 43200: 12h
 | 
|---|
| 35 | 86400: 1d
 | 
|---|
| 36 | 172800: 2d
 | 
|---|
| 37 | 604800: 7d (1w)
 | 
|---|
| 38 | 
 | 
|---|
| 39 | valid records:
 | 
|---|
| 40 | 
 | 
|---|
| 41 | nb:  wildcards are supported for most types.  use with extreme caution!  (I don't plan on writing
 | 
|---|
| 42 | tools that will create them.)
 | 
|---|
| 43 | 
 | 
|---|
| 44 | .fqdn:ip:x:ttl:timestamp:lo
 | 
|---|
| 45 |  -> x.fqdn is a nameserver at ip, SOA sets x.fqdn as master with hostmaster@fqdn as contact
 | 
|---|
| 46 |  -> if x contains a . that is used as the NS name
 | 
|---|
| 47 | (Not much use for us)
 | 
|---|
| 48 | 
 | 
|---|
| 49 | Zfqdn:primary:contact:serial:refresh:retry:expire:minttl:recttl:(timestamp:lo)
 | 
|---|
| 50 |  -> SOA for fqdn
 | 
|---|
| 51 | 
 | 
|---|
| 52 | &fqdn:ip:x:ttl:timestamp:lo
 | 
|---|
| 53 |  -> x.fqdn is a nameserver
 | 
|---|
| 54 |  -> if x contains a . that is used as the NS name
 | 
|---|
| 55 |  -> ip may be omitted;  A record for fqdn->ip is created otherwise
 | 
|---|
| 56 | 
 | 
|---|
| 57 | =fqdn:ip:ttl:timestamp:lo
 | 
|---|
| 58 |  -> A record and matching PTR record with fqdn and ip
 | 
|---|
| 59 | 
 | 
|---|
| 60 | +fqdn:ip:ttl:timestamp:lo
 | 
|---|
| 61 |  -> A record
 | 
|---|
| 62 | 
 | 
|---|
| 63 | ^ptr:fqdn:ttl:timestamp:lo
 | 
|---|
| 64 |  -> PTR record.  note ptr must be reverse-IP format ending in .in-addr.arpa
 | 
|---|
| 65 | 
 | 
|---|
| 66 | @fqdn:ip:x:dist:ttl:timestamp:lo
 | 
|---|
| 67 |  -> MX.  Dist defaults to 0.
 | 
|---|
| 68 |  -> ip may be omitted;  A record for fqdn->ip is created otherwise
 | 
|---|
| 69 | 
 | 
|---|
| 70 | -fqdn:ip:ttl:timestamp:lo
 | 
|---|
| 71 |  -> ignored
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 'fqdn:text:ttl:timestamp:lo
 | 
|---|
| 74 |  -> TXT record
 | 
|---|
| 75 |  -> octal-encode special characters in text as \nnn
 | 
|---|
| 76 | 
 | 
|---|
| 77 | Cfqdn:name:ttl:timestamp:lo
 | 
|---|
| 78 |  -> CNAME for fqdn pointing to name
 | 
|---|
| 79 | 
 | 
|---|
| 80 | :fqdn:n:data:ttl:timestamp:lo
 | 
|---|
| 81 |  -> Generic data, of type n (n is a 16-bit unsigned integer)
 | 
|---|
| 82 |     17 is RP
 | 
|---|
| 83 |     16 is TXT
 | 
|---|
| 84 |     2 (NS), 5 (CNAME), 6 (SOA), 12 (PTR), 15 (MX) and 252 (AXFR) (WTF?) should not be used
 | 
|---|
| 85 |  -> data must use octal escapes for : or nondisplayable characters.  axfr-get seems to escape all
 | 
|---|
| 86 |     non-alphanumerics, therefore so will we.
 | 
|---|
| 87 | 
 | 
|---|
| 88 | two primary groups of data:
 | 
|---|
| 89 | -> forward zones
 | 
|---|
| 90 |   -> local master zones
 | 
|---|
| 91 |   -> local slave zones
 | 
|---|
| 92 | -> reverse zones
 | 
|---|
| 93 | - note that it would be really nice to eliminate duplicated A records (+domain.com:ip:: plus =domain.com:ip::)
 | 
|---|
| 94 | 
 | 
|---|
| 95 | operations:
 | 
|---|
| 96 | -> import zone data (BIND*, djbdns, vegadns-mysql)
 | 
|---|
| 97 |   -> allow overwrite of existing SOA
 | 
|---|
| 98 | -> export data (BIND*, djbdns)
 | 
|---|
| 99 | -> add zone/domain
 | 
|---|
| 100 |   -> as slave
 | 
|---|
| 101 |   -> as master
 | 
|---|
| 102 | -> delete zone/domain
 | 
|---|
| 103 | -> add record to domain
 | 
|---|
| 104 | -> remove record from domain
 | 
|---|
| 105 | -> change record
 | 
|---|
| 106 |   -> A record IP
 | 
|---|
| 107 |   -> CNAME destination
 | 
|---|
| 108 |   -> MX destination
 | 
|---|
| 109 |   -> MX priority
 | 
|---|
| 110 |   -> A <-> CNAME ?
 | 
|---|
| 111 |   -> flag record as "primary" A record for an IP (means that PTR will set that name as rDNS)
 | 
|---|
| 112 | -> force propagation (execute propagation script)
 | 
|---|
| 113 | -> User ACL fiddling:
 | 
|---|
| 114 |   -> take IPDB model, include groups/delegation/etc
 | 
|---|
| 115 |     "admin" -> nominally full access to anything/everything
 | 
|---|
| 116 |     "staff" -> general access to all domains, can create users and delegate domains to them
 | 
|---|
| 117 |     "bulk hoster" -> customer with more than one domain, (can create users and delegate domains to them)?
 | 
|---|
| 118 |     "user" -> customer with one domain
 | 
|---|
| 119 |     
 | 
|---|
| 120 | 
 | 
|---|
| 121 | recommended SOA/TTL/etc times:
 | 
|---|
| 122 | refresh 86400 (24h), retry 7200 (2h), expire 2592000 (30d), ttl 345600 (4d)
 | 
|---|
| 123 | 
 | 
|---|
| 124 | Qs re: new servers:
 | 
|---|
| 125 | -> IPs for cache/authoritative?
 | 
|---|
| 126 | 
 | 
|---|
| 127 | 
 | 
|---|
| 128 | flow of data:
 | 
|---|
| 129 | user input -> database -> local "zone" data -> rsync/scp to slaves
 | 
|---|
| 130 | 
 | 
|---|
| 131 | don't use "domain ID" goop;  its only advantage is slightly lower disk use.  otherwise it's more
 | 
|---|
| 132 | complicated, less traceable thru the DB manually
 | 
|---|
| 133 | 
 | 
|---|
| 134 | 
 | 
|---|
| 135 | db structure (current)
 | 
|---|
| 136 | 
 | 
|---|
| 137 | domains:
 | 
|---|
| 138 | | domain_id   | int(11)                   |      | MUL | NULL     | auto_increment |
 | 
|---|
| 139 | | domain      | varchar(100)              |      |     |          |                |
 | 
|---|
| 140 | | group_id    | int(11)                   | YES  |     | NULL     |                |
 | 
|---|
| 141 | | description | varchar(255)              |      |     |          |                |
 | 
|---|
| 142 | | status      | enum('active','inactive') |      |     | inactive |                |
 | 
|---|
| 143 | 
 | 
|---|
| 144 | records:
 | 
|---|
| 145 | | domain_id   | int(11)      |      | MUL | 0       |                |
 | 
|---|
| 146 | | record_id   | int(11)      |      | PRI | NULL    | auto_increment |
 | 
|---|
| 147 | | host        | varchar(100) |      |     |         |                |
 | 
|---|
| 148 | | type        | char(1)      | YES  |     | NULL    |                |
 | 
|---|
| 149 | | val         | varchar(100) | YES  |     | NULL    |                |
 | 
|---|
| 150 | | distance    | int(4)       | YES  |     | 0       |                |
 | 
|---|
| 151 | | weight      | int(4)       | YES  |     | NULL    |                | - for SRV only
 | 
|---|
| 152 | | port        | int(4)       | YES  |     | NULL    |                | - for SRV only
 | 
|---|
| 153 | | ttl         | int(11)      |      |     | 86400   |                |
 | 
|---|
| 154 | | description | varchar(255) |      |     |         |                |
 | 
|---|
| 155 | 
 | 
|---|
| 156 | default_records is a duplicate of records structurally
 | 
|---|
| 157 | 
 | 
|---|
| 158 | log:  (not sure how useful this really is, in this form...)
 | 
|---|
| 159 | | domain_id | int(11)      |      |     | 0       |       |
 | 
|---|
| 160 | | user_id   | int(11)      |      |     | 0       |       |
 | 
|---|
| 161 | | group_id  | int(11)      |      |     | 0       |       |
 | 
|---|
| 162 | | email     | varchar(60)  |      |     |         |       |
 | 
|---|
| 163 | | name      | varchar(60)  |      |     |         |       |
 | 
|---|
| 164 | | entry     | varchar(200) |      |     |         |       |
 | 
|---|
| 165 | | time      | int(11)      |      |     | 0       |       |
 | 
|---|
| 166 | 
 | 
|---|
| 167 | db structure (proposed)
 | 
|---|
| 168 | 
 | 
|---|
| 169 | domains:
 | 
|---|
| 170 | domain  char(128)       pk, indexed
 | 
|---|
| 171 | group   char(32)        fk, indexed?
 | 
|---|
| 172 | status  enum?
 | 
|---|
| 173 | masterns char(64)
 | 
|---|
| 174 | email   char(128)
 | 
|---|
| 175 | serial  long int (needs 2^32 at least)
 | 
|---|
| 176 | refresh long int        needs semi-sane default
 | 
|---|
| 177 | retry   long int        needs semi-sane default
 | 
|---|
| 178 | expire  long int        needs semi-sane default
 | 
|---|
| 179 | minttl  long int        needs semi-sane default
 | 
|---|
| 180 | ctime   timestamp
 | 
|---|
| 181 | mtime   timestamp
 | 
|---|
| 182 | 
 | 
|---|
| 183 | records:
 | 
|---|
| 184 | recid   serial
 | 
|---|
| 185 | domain  char(128)       fk, indexed?
 | 
|---|
| 186 | host    char(128)       pk, indexed
 | 
|---|
| 187 | type    enum?
 | 
|---|
| 188 | val     char(256)       to allow for 255-char TXT records
 | 
|---|
| 189 | extra   char(10)        10 should be enough to express any needs for MX, SRV, or anything else...right?
 | 
|---|
| 190 | ttl     long int
 | 
|---|
| 191 | ctime   timestamp
 | 
|---|
| 192 | mtime   timestamp
 | 
|---|
| 193 | 
 | 
|---|
| 194 | default records to be either database-coded as default values or coded in er, code.
 | 
|---|
| 195 | -> hrm.
 | 
|---|
| 196 |   database-level defaults are "recommended practice" according to the cricket book
 | 
|---|
| 197 |   code-level defaults may be hardcoded (easy) or loaded from a config file (harder, but cleaner)
 | 
|---|
| 198 |   all must be overrideable by a database-table-stored "local policy defaults" widget
 | 
|---|
| 199 | 
 | 
|---|
| 200 | add domain:
 | 
|---|
| 201 |  -> need domain name
 | 
|---|
| 202 |  -> IP/"company default" radio button pair, with some Javascript to change defaults for:
 | 
|---|
| 203 |  -> radio buttons with sane defaults for standard hosts (www/mail/ftp/smtp)
 | 
|---|
| 204 |    -> www CNAME @
 | 
|---|
| 205 |    -> FTP CNAME @
 | 
|---|
| 206 |    -> mail CNAME mail.company.com
 | 
|---|
| 207 |    -> smtp CNAME smtp.company.com
 | 
|---|
| 208 |    -> MX defaults to <mxlist>
 | 
|---|
| 209 |    
 | 
|---|
| 210 | +----------------------------------------------------------------+
 | 
|---|
| 211 | | Domain: _________________________________                      |
 | 
|---|
| 212 | | o Company hosting       o Slave zone        o Custom settings  |
 | 
|---|
| 213 | +----------------------------------------------------------------+
 | 
|---|
| 214 | 
 | 
|---|
| 215 | add_domain($domain,$class)
 | 
|---|
| 216 | update_domain($domain,$group,$status,[$contact,$primary,$serial,$ttl,$refresh,$retry,$expire,$minttl])
 | 
|---|
| 217 | delete_domain($domain)
 | 
|---|
| 218 | lock_domain($domain)  -hm..  lock/unlock may be admin-level "don't touch!" flags vs "active/inactive" flags
 | 
|---|
| 219 | unlock_domain($domain)
 | 
|---|
| 220 | add_record($domain,$host,$type,$value,$extra,$ttl)
 | 
|---|
| 221 | update_record($id,$host,$type,$val,$extra,$ttl)
 | 
|---|
| 222 | delete_record($id)
 | 
|---|
| 223 | export_data($domain,$format) ->takes special <ALL> arg for all zones.  $format -> BIND or djb (implement DJB first)
 | 
|---|
| 224 | update_nameservers()
 | 
|---|
| 225 | 
 | 
|---|