diff --git a/kolla_ansible/cmd/genpwd.py b/kolla_ansible/cmd/genpwd.py
index b8b176e338..e523372e22 100755
--- a/kolla_ansible/cmd/genpwd.py
+++ b/kolla_ansible/cmd/genpwd.py
@@ -16,6 +16,7 @@ import argparse
 import hmac
 import os
 import random
+import stat
 import string
 import sys
 
@@ -63,6 +64,14 @@ def genpwd(passwords_file, length, uuid_keys, ssh_keys, blank_keys,
         print(f"ERROR: Passwords file \"{passwords_file}\" is missing")
         sys.exit(1)
 
+    if os.stat(passwords_file).st_mode & stat.S_IROTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-readable. The permissions will be changed.")
+
+    if os.stat(passwords_file).st_mode & stat.S_IWOTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-writeable. The permissions will be changed.")
+
     if not isinstance(passwords, dict):
         print("ERROR: Passwords file not in expected key/value format")
         sys.exit(1)
@@ -96,7 +105,15 @@ def genpwd(passwords_file, length, uuid_keys, ssh_keys, blank_keys,
                     for n in range(length)
                 ])
 
-    with open(passwords_file, 'w') as f:
+    try:
+        os.remove(passwords_file)
+    except OSError:
+        pass
+
+    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
+    mode = 0o640
+
+    with os.fdopen(os.open(passwords_file, flags, mode=mode), 'w') as f:
         f.write(yaml.safe_dump(passwords, default_flow_style=False))
 
 
diff --git a/kolla_ansible/cmd/mergepwd.py b/kolla_ansible/cmd/mergepwd.py
index f7d3c7c50a..00f38d9760 100755
--- a/kolla_ansible/cmd/mergepwd.py
+++ b/kolla_ansible/cmd/mergepwd.py
@@ -13,6 +13,8 @@
 # limitations under the License.
 
 import argparse
+import os
+import stat
 import sys
 import yaml
 
@@ -21,9 +23,21 @@ def mergepwd(old, new, final, clean=False):
     with open(old, "r") as old_file:
         old_passwords = yaml.safe_load(old_file)
 
+    if os.stat(old).st_mode & stat.S_IROTH:
+        print(f"WARNING: Passwords file \"{old}\" is world-readable.")
+
+    if os.stat(old).st_mode & stat.S_IWOTH:
+        print(f"WARNING: Passwords file \"{old}\" is world-writeable.")
+
     with open(new, "r") as new_file:
         new_passwords = yaml.safe_load(new_file)
 
+    if os.stat(new).st_mode & stat.S_IROTH:
+        print(f"WARNING: Passwords file \"{new}\" is world-readable.")
+
+    if os.stat(new).st_mode & stat.S_IWOTH:
+        print(f"WARNING: Passwords file \"{new}\" is world-writeable.")
+
     if not isinstance(old_passwords, dict):
         print("ERROR: Old passwords file not in expected key/value format")
         sys.exit(1)
@@ -41,7 +55,15 @@ def mergepwd(old, new, final, clean=False):
         # old behavior
         new_passwords.update(old_passwords)
 
-    with open(final, "w") as destination:
+    try:
+        os.remove(final)
+    except OSError:
+        pass
+
+    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
+    mode = 0o640
+
+    with os.fdopen(os.open(final, flags, mode=mode), 'w') as destination:
         yaml.safe_dump(new_passwords, destination, default_flow_style=False)
 
 
diff --git a/kolla_ansible/cmd/readpwd.py b/kolla_ansible/cmd/readpwd.py
index 87bdf6ff5b..b06c7f7df8 100755
--- a/kolla_ansible/cmd/readpwd.py
+++ b/kolla_ansible/cmd/readpwd.py
@@ -14,6 +14,7 @@
 
 import argparse
 import os
+import stat
 import sys
 
 import hvac
@@ -29,6 +30,14 @@ def readpwd(passwords_file, vault_kv_path, vault_mount_point, vault_namespace,
     with open(passwords_file, 'r') as f:
         passwords = yaml.safe_load(f.read())
 
+    if os.stat(passwords_file).st_mode & stat.S_IROTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-readable. The permissions will be changed.")
+
+    if os.stat(passwords_file).st_mode & stat.S_IWOTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-writeable. The permissions will be changed.")
+
     if not isinstance(passwords, dict):
         print("ERROR: Passwords file not in expected key/value format")
         sys.exit(1)
@@ -53,7 +62,15 @@ def readpwd(passwords_file, vault_kv_path, vault_mount_point, vault_namespace,
         except KeyError:
             vault_kv_passwords[password_key] = password_data['data']['data']
 
-    with open(passwords_file, 'w') as f:
+    try:
+        os.remove(passwords_file)
+    except OSError:
+        pass
+
+    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
+    mode = 0o640
+
+    with os.fdopen(os.open(passwords_file, flags, mode=mode), 'w') as f:
         yaml.safe_dump(vault_kv_passwords, f)
 
 
diff --git a/kolla_ansible/cmd/writepwd.py b/kolla_ansible/cmd/writepwd.py
index 9a3eb0d810..0227fcdd44 100755
--- a/kolla_ansible/cmd/writepwd.py
+++ b/kolla_ansible/cmd/writepwd.py
@@ -14,6 +14,7 @@
 
 import argparse
 import os
+import stat
 import sys
 
 import hvac
@@ -25,9 +26,18 @@ from kolla_ansible.hashi_vault import hashicorp_vault_client
 def writepwd(passwords_file, vault_kv_path, vault_mount_point, vault_namespace,
              vault_addr, vault_role_id, vault_secret_id, vault_token,
              vault_cacert):
+
     with open(passwords_file, 'r') as f:
         passwords = yaml.safe_load(f.read())
 
+    if os.stat(passwords_file).st_mode & stat.S_IROTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-readable.")
+
+    if os.stat(passwords_file).st_mode & stat.S_IWOTH:
+        print(f"WARNING: Passwords file \"{passwords_file}\" is"
+              " world-writeable.")
+
     if not isinstance(passwords, dict):
         print("ERROR: Passwords file not in expected key/value format")
         sys.exit(1)
diff --git a/releasenotes/notes/fix-passwords-yml-permissions-ca73638b71aeadf4.yaml b/releasenotes/notes/fix-passwords-yml-permissions-ca73638b71aeadf4.yaml
new file mode 100644
index 0000000000..118f4a4b0d
--- /dev/null
+++ b/releasenotes/notes/fix-passwords-yml-permissions-ca73638b71aeadf4.yaml
@@ -0,0 +1,7 @@
+---
+security:
+  - |
+    The kolla-genpwd, kolla-mergepwd, kolla-readpwd and kolla-writepwd
+    commands now creates or updates passwords.yml with correct
+    permissions. Also they display warning message about incorrect
+    permissions.
diff --git a/tests/run-hashi-vault.yml b/tests/run-hashi-vault.yml
index 136951e90c..2fa79663bc 100644
--- a/tests/run-hashi-vault.yml
+++ b/tests/run-hashi-vault.yml
@@ -45,6 +45,7 @@
       copy:
         src: "{{ kolla_ansible_src_dir }}/etc/kolla/passwords.yml"
         dest: /etc/kolla/passwords.yml
+        mode: "0640"
         remote_src: true
 
     - name: generate passwords
diff --git a/tests/run.yml b/tests/run.yml
index 8c5f3c9701..e693db446a 100644
--- a/tests/run.yml
+++ b/tests/run.yml
@@ -285,6 +285,7 @@
       copy:
         src: "{{ kolla_ansible_src_dir }}/etc/kolla/passwords.yml"
         dest: /etc/kolla/passwords.yml
+        mode: "0640"
         remote_src: true
 
     - name: generate passwords
@@ -671,6 +672,7 @@
           copy:
             src: "{{ kolla_ansible_src_dir }}/etc/kolla/passwords.yml"
             dest: /etc/kolla/passwords.yml
+            mode: "0640"
             remote_src: true
 
         - name: generate new passwords