octodns / octodns-bind

RFC compliant (Bind9) provider for octoDNS
MIT License
7 stars 12 forks source link

ZoneFileProvider writes IDN domains without encoding #68

Open asalmela opened 1 day ago

asalmela commented 1 day ago

I was aiming to create a scheduled backup of DNS zones hosted at one cloud provider in a bind compatible format using octodns, and to my surprise IDN records and zone file name were converted to their UTF-8 presentation when written out by ZoneFileProvider.

Is this intentional?

I have included a minimal reproducer:

$ cat idn-config.yml 
providers:
  zonefile-in:
    class: octodns_bind.ZoneFileProvider
    directory: ./input
    check_origin: false

  zonefile-out:
    class: octodns_bind.ZoneFileProvider
    directory: ./output

zones:
    '*':
        sources:
            - zonefile-in
        targets:
            - zonefile-out
$ cat input/xn--bcher-kva.example. 
$ORIGIN xn--bcher-kva.example.

@ 3600 IN SOA ns.xn--bcher-kva.example. hostmaster.xn--bcher-kva.example.(
    1732013604 ; Serial
    3600 ; Refresh
    600 ; Retry
    604800 ; Expire
    3600 ; NXDOMAIN ttl
)

@ 3600 IN A 127.0.0.1
$ octodns-sync --config idn-config.yml --doit
2024-12-02T09:33:34  [139583356670080] INFO  Manager __init__: config_file=idn-config.yml, (octoDNS 1.10.0)
2024-12-02T09:33:34  [139583356670080] INFO  Manager _config_executor: max_workers=1
2024-12-02T09:33:34  [139583356670080] INFO  Manager _config_include_meta: include_meta=False
2024-12-02T09:33:34  [139583356670080] INFO  Manager _config_enable_checksum: enable_checksum=False
2024-12-02T09:33:34  [139583356670080] INFO  Manager _config_auto_arpa: auto_arpa=False
2024-12-02T09:33:34  [139583356670080] INFO  Manager __init__: global_processors=[]
2024-12-02T09:33:34  [139583356670080] INFO  Manager __init__: global_post_processors=[]
2024-12-02T09:33:35  [139583356670080] INFO  Manager __init__: provider=zonefile-in (octodns_bind 0.0.6)
2024-12-02T09:33:35  [139583356670080] INFO  Manager __init__: provider=zonefile-out (octodns_bind 0.0.6)
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync: eligible_zones=[], eligible_targets=[], dry_run=False, force=False, plan_output_fh=<stdout>, checksum=None
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:     sources=['zonefile-in']
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:   dynamic zone=*, sources=None
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:     adding dynamic zone=xn--bcher-kva.example.
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:   zone=bücher.example.
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:     sources=['zonefile-in']
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:     processors=[]
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:     targets=['zonefile-out']
2024-12-02T09:33:35  [139583356670080] INFO  ZoneFileProvider[zonefile-in] populate:   found 1 records
2024-12-02T09:33:35  [139583356670080] INFO  ZoneFileProvider[zonefile-out] plan: desired=bücher.example.
2024-12-02T09:33:35  [139583356670080] INFO  ZoneFileProvider[zonefile-out] populate:   found 0 records
2024-12-02T09:33:35  [139583356670080] WARNING ZoneFileProvider[zonefile-out] root NS record supported, but no record is configured for bücher.example.
2024-12-02T09:33:35  [139583356670080] INFO  ZoneFileProvider[zonefile-out] plan:   Creates=1, Updates=0, Deletes=0, Existing Records=0
2024-12-02T09:33:35  [139583356670080] INFO  Plan 
********************************************************************************
* bücher.example.
********************************************************************************
* zonefile-out (ZoneFileProvider)
*   Create Zone<bücher.example.>
*   Create <ARecord A 3600, bücher.example., ['127.0.0.1']> ()
*   Summary: Creates=1, Updates=0, Deletes=0, Existing Records=0
********************************************************************************

2024-12-02T09:33:35  [139583356670080] INFO  ZoneFileProvider[zonefile-out] apply: making 1 changes to bücher.example.
2024-12-02T09:33:35  [139583356670080] WARNING ZoneFileProvider[zonefile-out] _primary_nameserver: unable to find a primary_nameserver for bücher.example., using placeholder
2024-12-02T09:33:35  [139583356670080] INFO  Manager sync:   1 total changes
$ ls -l output/
total 4
-rw-rw-r-- 1 as as 228 Dec  2 09:33 bücher.example.
$ cat output/bücher.example. 
$ORIGIN bücher.example.

@ 3600 IN SOA ns.bücher.example. webmaster.bücher.example. (
    1733124815 ; Serial
    3600 ; Refresh
    600 ; Retry
    604800 ; Expire
    3600 ; NXDOMAIN ttl
)

@     3600 IN A        127.0.0.1
ross commented 1 day ago

Is this intentional?

Probably not, likely something that wasn't specifically targeted and just did the default. I take it that bind file format wants the idna form?

It should just be a matter of switching to use the encoded name here:

https://github.com/octodns/octodns-bind/blob/b974df8f06ce5dfd205ec5042ccd97aa75a74929/octodns_bind/__init__.py#L301

Though it probably also makes sense to include a comment with the decoded version for human consumption.

I'm also wondering what would happen with the AxfrPopulate setups.