     [infra-file :- schema/Str]
     (line-seq (io/reader infra-file)))
 
+(defn- write-infra-serials-to-writer
+  [writer infra-nodes-path infra-node-serials-path signeddir]
+  (try
+    (let [infra-nodes (read-infra-nodes infra-nodes-path)]
+      (doseq [infra-node infra-nodes]
+        (try
+          (let [infra-serial (-> (path-to-cert signeddir infra-node)
+                                 (utils/pem->cert)
+                                 (utils/get-serial))]
+            (.write writer (str infra-serial))
+            (.newLine writer))
+          (catch java.io.FileNotFoundException ex
+            (log/warn
+             (i18n/trs
+              (str
+               "Failed to find/load certificate for Puppet Infrastructure Node:"
+               infra-node)))))))
+    (catch java.io.FileNotFoundException ex
+      (log/warn (i18n/trs (str infra-nodes-path " does not exist"))))))
+
 (schema/defn generate-infra-serials
   "Given a list of infra nodes it will create a file containing
    serial numbers of their certificates (listed on separate lines).
    It is expected have at least one entry (MoM)"
-   [{:keys [infra-nodes-path infra-node-serials-path signeddir]} :- CaSettings]
-   (with-open [wtr (io/writer infra-node-serials-path)]
-     (try
-       (let [infra-nodes (read-infra-nodes infra-nodes-path)]
-         (doseq [infra-node infra-nodes]
-           (try
-             (let [infra-serial (-> (path-to-cert signeddir infra-node)
-                                 (utils/pem->cert)
-                                 (utils/get-serial))]
-               (.write wtr (str infra-serial))
-               (.newLine wtr))
-            (catch java.io.FileNotFoundException ex
-               (log/warn
-                 (i18n/trs
-                   (str
-                     "Failed to find/load certificate for Puppet Infrastructure Node:"
-                     infra-node)))))))
-       (catch java.io.FileNotFoundException ex
-         (log/warn (i18n/trs (str infra-nodes-path " does not exist")))))))
+  [{:keys [infra-nodes-path infra-node-serials-path signeddir]} :- CaSettings]
+  (ks-file/atomic-write infra-node-serials-path
+                        #(write-infra-serials-to-writer %
+                                                        infra-nodes-path
+                                                        infra-node-serials-path
+                                                        signeddir)
+                        public-key-perms))
 
 (schema/defn generate-ssl-files!
   "Given the CA settings, generate and write to disk all of the necessary

                                             (.getPublicKey cacert)))]
    (log/info (i18n/trs "Signed certificate request for {0}" subject))
    (write-cert-to-inventory! signed-cert cert-inventory)
    (utils/cert->pem! signed-cert (path-to-cert signeddir subject))))

(schema/defn ^:always-validate
  save-certificate-request!

                        (i18n/tru "CSR ''{0}'' contains subject alternative names ({1}), which are disallowed." subject (str/join ", " subject-alt-names))
                        (i18n/tru "To allow subject alternative names, set allow-subject-alt-names to true in your puppetserver.conf file.")
                        (i18n/tru "Then restart the puppetserver and try signing this certificate again."))})))))

(schema/defn ^:always-validate process-csr-submission!
  "Given a CSR for a subject (typically from the HTTP endpoint),
   perform policy checks and sign or save the CSR (based on autosign).
