DNSControl – Office 365 Record Generator

DNSControl is a fantastic tool to manage DNS records, especially if there are multiple DNS zones being managed:

  • DNS records in plain text files allowing them to be stored in a VCS of your choice
  • Records are vendor agnostic; switch from one DNS provider to another without having to import/export records or put them in a certain format
  • Make DNS changes part of a CI/CD pipeline
  • Use functions, variables, macros; a subset of JavaScript features are available

There are many more advantages/features which I will not cover in this post. I also won’t go into basic configuration of DNSControl in this post. The documentation covers that pretty well and there are a variety of other posts that can help with the basics:

Contents

The Problem

When using Office 365, there is quite a few records which need to be set typically:

  • Validation TXT record (at least initially to prove ownership of the domain)
  • MX record
  • DKIM CNAME records
  • Skype for Business discovery SRV/CNAME records
  • CNAME records for Azure AD device enrollment
  • TXT record for SPF
  • TXT record for DMARC

If using all of those features it quickly add up to 12 DNS records to add. Managing these manually (especially for a large number of domains) can be error prone at worst and time consuming at best.

The Solution: Office 365 Generator

Using DNSControl, all of the Office 365 records can be abstracted into a single function call in a DNS zone which is much more convenient: Office365()

The relevant files an example DNSControl configuration is available on GitHub here: dnscontrol-office365

File Structure

Rather than putting everything into a single dnsconfig.js file, I like to split things up a bit. I am using the following file/directory structure:

.
.
├── creds.json
├── dnsconfig.json
├── domains
│   ├── example1.com.js
│   ├── example2.com.js
│   └── example3.com.js
├── functions
|   ├── DKIMRecord.js
|   ├── DMARCRecord.js
|   ├── Office365.js
│   └── SPFRecord.js
├── records
│   └── Office365.js
└── vars
    ├── Office365.js
    ├── SPF.js
    └── TTL.js

There are two domains being managed with DNSControl; example1.com and example2.com.

Main Configuration (dnsconfig.json)

The main dnsconfig.json file needs to include the relevant files (DNS zones, functions, records and vars (variables). The order that the directories are included is important; the Office365 records rely on functions which rely on variables.

Variables (vars/)

I make use of two variable files; one to contain the default TTL that I use for all records (TTL.js) and the other containing common configuration for Office 365 (tenant name, MX record host name).

vars/TTL.js

The default TTL can be set to your preferred value. If required, you can also override this on a per-domain basis later.

vars/Office365.js

This file contains the tenant name and MX record hostname that will be built. For the purposes of this example the Office 365 tenant name is “example“. MX records will be on the hostname “mail.protection.outlook.com” with a priority of 0. If you have domains inside different tenants you may override the tenant name later if required.

vars/SPF.js

This file contains SPF record definitions. You can add common SPF record variables here for use in the domain configuration files.

Functions (functions/)

The main “Office365()” function calls various smaller functions from functions/Office365.js. As an example, to add the MX record the function “Office365MX()” will be used.

A function has also been defined to add the SPF record and DMARC record. The DMARC record function assumes a strict SPF/DKIM alignment policy with reports by default being sent to dmarc-rua@$domain and dmarc-ruf@$domain.

Records (records/)

The main “Office365()” function is defined in records/Office365.js.

Usage/Examples

All functions are documented using JSDoc. If you need examples specific to your case check the relevant file and the comments should explain the variables.

Example domain configuration files are available in the domains directory.

The basic domain definition looks like this:

D(
  "example.com",                  // The domain name
  // Registrar and DNS providers
  REG_NAMECHEAP,                  // The registrar of the domain name
  DnsProvider(DNS_CLOUDFLARE),    // The DNS provider that will be managed

  // Add Office 365 records
  // This will setup SPF, DKIM, DMARC, auto discovery, MX
  Office365(
    "example.com"                 // The domain name - This will be used to build records
    // { "...": "..." }           // Optional parameters
    // { "...": "..." }           // Optional features control
  ),

  // Custom DNS records
  A("@", "192.0.2.1", CF_PROXY_ON),
  AAAA("@", "2001:db8::1", CF_PROXY_ON),
  CNAME("www", "example.com.", CF_PROXY_ON)
);

Leave a Reply

Your email address will not be published. Required fields are marked *