Repository: certbot/certbot

Issue:
Put a README in /etc/letsencrypt/live
In addition to putting a README in /etc/letsencrypt/live/example.com, a lot of people work directly in /etc/letsencrypt/live, so we should probably put a README in there telling people not to move certs.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5dd51ef16..20e82b5d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,8 @@ Certbot adheres to [Semantic Versioning](http://semver.org/).
 
 ### Changed
 
-*  `--manual` will explicitly warn users that earlier challenges should remain in place when setting up subsequent challenges.
+* Write README to the base of (config-dir)/live directory
+* `--manual` will explicitly warn users that earlier challenges should remain in place when setting up subsequent challenges.
 
 ### Fixed
 
diff --git a/acme/acme/messages.py b/acme/acme/messages.py
index 5be458580..7e86b0c3b 100644
--- a/acme/acme/messages.py
+++ b/acme/acme/messages.py
@@ -523,7 +523,7 @@ class Order(ResourceBody):
     """
     identifiers = jose.Field('identifiers', omitempty=True)
     status = jose.Field('status', decoder=Status.from_json,
-                        omitempty=True, default=STATUS_PENDING)
+                        omitempty=True)
     authorizations = jose.Field('authorizations', omitempty=True)
     certificate = jose.Field('certificate', omitempty=True)
     finalize = jose.Field('finalize', omitempty=True)
@@ -553,4 +553,3 @@ class OrderResource(ResourceWithURI):
 class NewOrder(Order):
     """New order."""
     resource_type = 'new-order'
-    resource = fields.Resource(resource_type)
diff --git a/certbot/storage.py b/certbot/storage.py
index 32d6771c2..c16ea35b8 100644
--- a/certbot/storage.py
+++ b/certbot/storage.py
@@ -214,6 +214,26 @@ def get_link_target(link):
         target = os.path.join(os.path.dirname(link), target)
     return os.path.abspath(target)
 
+def _write_live_readme_to(readme_path, is_base_dir=False):
+    prefix = ""
+    if is_base_dir:
+        prefix = "[cert name]/"
+    with open(readme_path, "w") as f:
+        logger.debug("Writing README to %s.", readme_path)
+        f.write("This directory contains your keys and certificates.\n\n"
+                "`{prefix}privkey.pem`  : the private key for your certificate.\n"
+                "`{prefix}fullchain.pem`: the certificate file used in most server software.\n"
+                "`{prefix}chain.pem`    : used for OCSP stapling in Nginx >=1.3.7.\n"
+                "`{prefix}cert.pem`     : will break many server configurations, and "
+                                    "should not be used\n"
+                "                 without reading further documentation (see link below).\n\n"
+                "WARNING: DO NOT MOVE OR RENAME THESE FILES!\n"
+                "         Certbot expects these files to remain in this location in order\n"
+                "         to function properly!\n\n"
+                "We recommend not moving these files. For more information, see the Certbot\n"
+                "User Guide at https://certbot.eff.org/docs/using.html#where-are-my-"
+                                    "certificates.\n".format(prefix=prefix))
+
 
 def _relevant(option):
     """
@@ -1003,6 +1023,9 @@ class RenewableCert(object):
                 logger.debug("Creating directory %s.", i)
         config_file, config_filename = util.unique_lineage_name(
             cli_config.renewal_configs_dir, lineagename)
+        base_readme_path = os.path.join(cli_config.live_dir, README)
+        if not os.path.exists(base_readme_path):
+            _write_live_readme_to(base_readme_path, is_base_dir=True)
 
         # Determine where on disk everything will go
         # lineagename will now potentially be modified based on which
@@ -1045,21 +1068,7 @@ class RenewableCert(object):
 
         # Write a README file to the live directory
         readme_path = os.path.join(live_dir, README)
-        with open(readme_path, "w") as f:
-            logger.debug("Writing README to %s.", readme_path)
-            f.write("This directory contains your keys and certificates.\n\n"
-                    "`privkey.pem`  : the private key for your certificate.\n"
-                    "`fullchain.pem`: the certificate file used in most server software.\n"
-                    "`chain.pem`    : used for OCSP stapling in Nginx >=1.3.7.\n"
-                    "`cert.pem`     : will break many server configurations, and "
-                                        "should not be used\n"
-                    "                 without reading further documentation (see link below).\n\n"
-                    "WARNING: DO NOT MOVE THESE FILES!\n"
-                    "         Certbot expects these files to remain in this location in order\n"
-                    "         to function properly!\n\n"
-                    "We recommend not moving these files. For more information, see the Certbot\n"
-                    "User Guide at https://certbot.eff.org/docs/using.html#where-are-my-"
-                                        "certificates.\n")
+        _write_live_readme_to(readme_path)
 
         # Document what we've done in a new renewal config file
         config_file.close()


Test patch:
diff --git a/acme/acme/messages_test.py b/acme/acme/messages_test.py
index 0e2d8c62d..876fbe825 100644
--- a/acme/acme/messages_test.py
+++ b/acme/acme/messages_test.py
@@ -424,6 +424,19 @@ class OrderResourceTest(unittest.TestCase):
             'authorizations': None,
         })
 
+class NewOrderTest(unittest.TestCase):
+    """Tests for acme.messages.NewOrder."""
+
+    def setUp(self):
+        from acme.messages import NewOrder
+        self.reg = NewOrder(
+            identifiers=mock.sentinel.identifiers)
+
+    def test_to_partial_json(self):
+        self.assertEqual(self.reg.to_json(), {
+            'identifiers': mock.sentinel.identifiers,
+        })
+
 
 if __name__ == '__main__':
     unittest.main()  # pragma: no cover
diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py
index 53a976f8d..078a2858f 100644
--- a/certbot/tests/storage_test.py
+++ b/certbot/tests/storage_test.py
@@ -625,6 +625,8 @@ class RenewableCertTests(BaseRenewableCertTest):
         self.assertTrue(result._consistent())
         self.assertTrue(os.path.exists(os.path.join(
             self.config.renewal_configs_dir, "the-lineage.com.conf")))
+        self.assertTrue(os.path.exists(os.path.join(
+            self.config.live_dir, "README")))
         self.assertTrue(os.path.exists(os.path.join(
             self.config.live_dir, "the-lineage.com", "README")))
         with open(result.fullchain, "rb") as f: