{"id":10055,"date":"2023-06-08T09:05:09","date_gmt":"2023-06-08T14:05:09","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=10055"},"modified":"2023-06-18T10:40:31","modified_gmt":"2023-06-18T15:40:31","slug":"maintaining-an-etc-hosts-record","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=10055","title":{"rendered":"Maintaining an \/etc\/hosts record"},"content":{"rendered":"\n<p>I encountered an oddity at work &#8212; there&#8217;s a server on an internally located public IP space. Because it&#8217;s public space, it is not allowed to communicate with the internal interface of some of our security group&#8217;s servers. It <em>has<\/em> to use their public interface (not technically, just a policy on which they will not budge). I cannot just use a DNS server that resolves the public copy of our zone because then we&#8217;d lose access to <em>everything else<\/em>, so we are stuck making an \/etc\/hosts entry. Except this thing changes IPs fairly regularly (hey, we&#8217;re moving from AWS to Azure; hey, let&#8217;s try CloudFlare; nope, that is expensive so change it back) and the service it provides is <em>application authentication<\/em> so not something you want randomly falling over every couple of months.<\/p>\n\n\n\n<p>So I&#8217;ve come up with a quick script to maintain the \/etc\/hosts record for the endpoint. <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# requires: dnspython, subprocess\n\nimport dns.resolver\nimport subprocess\n\nstrHostToCheck = &#039;hostname.example.com&#039; # PingID endpoint for authentication\nstrDNSServer = &quot;8.8.8.8&quot;         # Google&#039;s public DNS server\nlistStrIPs = &#x5B;]\n\n# Get current assignement from hosts file\nlistCurrentAssignment = &#x5B; line for line in open(&#039;\/etc\/hosts&#039;) if strHostToCheck in line]\n\nif len(listCurrentAssignment) &gt;= 1:\n        strCurrentAssignment = listCurrentAssignment&#x5B;0].split(&quot;\\t&quot;)&#x5B;0]\n\n        # Get actual assignment from DNS\n        objResolver = dns.resolver.Resolver()\n        objResolver.nameservers = &#x5B;strDNSServer]\n        objHostResolution = objResolver.query(strHostToCheck)\n\n        for objARecord in objHostResolution:\n                listStrIPs.append(objARecord.to_text())\n\n        if len(listStrIPs) &gt;= 1:\n                # Fix \/etc\/hosts if the assignment there doesn&#039;t match DNS\n                if strCurrentAssignment in listStrIPs:\n                        print(f&quot;Nothing to do -- hosts file record {strCurrentAssignment} is in {listStrIPs}&quot;)\n                else:\n                        print(f&quot;I do not find {strCurrentAssignment} here, so now fix it!&quot;)\n                        subprocess.call(&#x5B;f&quot;sed -i -e &#039;s\/{strCurrentAssignment}\\t{strHostToCheck}\/{listStrIPs&#x5B;0]}\\t{strHostToCheck}\/g&#039; \/etc\/hosts&quot;], shell=True)\n        else:\n                print(&quot;No resolution from DNS ... that&#039;s not great&quot;)\nelse:\n        print(&quot;No assignment found in \/etc\/hosts ... that&#039;s not great either&quot;)\n\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>I encountered an oddity at work &#8212; there&#8217;s a server on an internally located public IP space. Because it&#8217;s public space, it is not allowed to communicate with the internal interface of some of our security group&#8217;s servers. It has to use their public interface (not technically, just a policy on which they will not &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,30],"tags":[100,1853,294,664],"class_list":["post-10055","post","type-post","status-publish","format-standard","hentry","category-coding","category-system-administration","tag-dns","tag-hosts-file","tag-linux","tag-python"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/10055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10055"}],"version-history":[{"count":2,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/10055\/revisions"}],"predecessor-version":[{"id":10089,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/10055\/revisions\/10089"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}