diff --git a/homeassistant/scripts/credstash.py b/homeassistant/scripts/credstash.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ba945626e2e15ef55735789a247787cb561e4f1
--- /dev/null
+++ b/homeassistant/scripts/credstash.py
@@ -0,0 +1,71 @@
+"""Script to get, put and delete secrets stored in credstash."""
+import argparse
+import getpass
+
+from homeassistant.util.yaml import _SECRET_NAMESPACE
+
+REQUIREMENTS = ['credstash==1.13.2', 'botocore==1.4.93']
+
+
+def run(args):
+    """Handle credstash script."""
+    parser = argparse.ArgumentParser(
+        description=("Modify Home-Assistant secrets in credstash."
+                     "Use the secrets in configuration files with: "
+                     "!secret <name>"))
+    parser.add_argument(
+        '--script', choices=['credstash'])
+    parser.add_argument(
+        'action', choices=['get', 'put', 'del', 'list'],
+        help="Get, put or delete a secret, or list all available secrets")
+    parser.add_argument(
+        'name', help="Name of the secret", nargs='?', default=None)
+    parser.add_argument(
+        'value', help="The value to save when putting a secret",
+        nargs='?', default=None)
+
+    import credstash
+    import botocore
+
+    args = parser.parse_args(args)
+    table = _SECRET_NAMESPACE
+
+    try:
+        credstash.listSecrets(table=table)
+    except botocore.errorfactory.ClientError:
+        credstash.createDdbTable(table=table)
+
+    if args.action == 'list':
+        secrets = [i['name'] for i in credstash.listSecrets(table=table)]
+        deduped_secrets = sorted(set(secrets))
+
+        print('Saved secrets:')
+        for secret in deduped_secrets:
+            print(secret)
+        return 0
+
+    if args.name is None:
+        parser.print_help()
+        return 1
+
+    if args.action == 'put':
+        if args.value:
+            the_secret = args.value
+        else:
+            the_secret = getpass.getpass('Please enter the secret for {}: '
+                                         .format(args.name))
+        current_version = credstash.getHighestVersion(args.name, table=table)
+        credstash.putSecret(args.name,
+                            the_secret,
+                            version=int(current_version) + 1,
+                            table=table)
+        print('Secret {} put successfully'.format(args.name))
+    elif args.action == 'get':
+        the_secret = credstash.getSecret(args.name, table=table)
+        if the_secret is None:
+            print('Secret {} not found'.format(args.name))
+        else:
+            print('Secret {}={}'.format(args.name, the_secret))
+    elif args.action == 'del':
+        credstash.deleteSecrets(args.name, table=table)
+        print('Deleted secret {}'.format(args.name))
diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py
index 7827f484fdf2d6eca66050077baa1ab9deaff9fa..fb682ac6f197dd240cd587b58ef5b0ff1df13d6f 100644
--- a/homeassistant/util/yaml.py
+++ b/homeassistant/util/yaml.py
@@ -12,6 +12,11 @@ try:
 except ImportError:
     keyring = None
 
+try:
+    import credstash
+except ImportError:
+    credstash = None
+
 from homeassistant.exceptions import HomeAssistantError
 
 _LOGGER = logging.getLogger(__name__)
@@ -257,6 +262,15 @@ def _secret_yaml(loader: SafeLineLoader,
             _LOGGER.debug("Secret %s retrieved from keyring", node.value)
             return pwd
 
+    if credstash:
+        try:
+            pwd = credstash.getSecret(node.value, table=_SECRET_NAMESPACE)
+            if pwd:
+                _LOGGER.debug("Secret %s retrieved from credstash", node.value)
+                return pwd
+        except credstash.ItemNotFound:
+            pass
+
     _LOGGER.error("Secret %s not defined", node.value)
     raise HomeAssistantError(node.value)
 
diff --git a/pylintrc b/pylintrc
index e94cbffe9f9369377742b4c5995dc86a0223a7f2..1ed8d2af3363ec7f462441152a84008345055615 100644
--- a/pylintrc
+++ b/pylintrc
@@ -14,6 +14,8 @@ reports=no
 # too-few-* - same as too-many-*
 # abstract-method - with intro of async there are always methods missing
 
+generated-members=botocore.errorfactory
+
 disable=
   abstract-class-little-used,
   abstract-class-not-used,
diff --git a/requirements_all.txt b/requirements_all.txt
index 10036a0361570a296a39157726ad5c0e0a7fa0a5..aa99cd03701836adc6a1184660a18991fa810977 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -115,6 +115,9 @@ blockchain==1.3.3
 # homeassistant.components.tts.amazon_polly
 boto3==1.4.3
 
+# homeassistant.scripts.credstash
+botocore==1.4.93
+
 # homeassistant.components.sensor.broadlink
 # homeassistant.components.switch.broadlink
 broadlink==0.5
@@ -136,6 +139,9 @@ colorlog>2.1,<3
 # homeassistant.components.binary_sensor.concord232
 concord232==0.14
 
+# homeassistant.scripts.credstash
+credstash==1.13.2
+
 # homeassistant.components.sensor.crimereports
 crimereports==1.0.0
 
diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py
index 0ccb6f5d6d08dec197cfb9e52337408527b1c7f2..c2eda2401f50f64e3ad76e434eb708a0d973771f 100644
--- a/tests/util/test_yaml.py
+++ b/tests/util/test_yaml.py
@@ -2,6 +2,7 @@
 import io
 import os
 import unittest
+import logging
 from unittest.mock import patch
 
 from homeassistant.exceptions import HomeAssistantError
@@ -372,6 +373,16 @@ class TestSecrets(unittest.TestCase):
         _yaml = load_yaml(self._yaml_path, yaml_str)
         self.assertEqual({'http': {'api_password': 'yeah'}}, _yaml)
 
+    @patch.object(yaml, 'credstash')
+    def test_secrets_credstash(self, mock_credstash):
+        """Test credstash fallback & get_password."""
+        mock_credstash.getSecret.return_value = 'yeah'
+        yaml_str = 'http:\n  api_password: !secret http_pw_credstash'
+        _yaml = load_yaml(self._yaml_path, yaml_str)
+        log = logging.getLogger()
+        log.error(_yaml['http'])
+        self.assertEqual({'api_password': 'yeah'}, _yaml['http'])
+
     def test_secrets_logger_removed(self):
         """Ensure logger: debug was removed."""
         with self.assertRaises(yaml.HomeAssistantError):