summaryrefslogtreecommitdiff
path: root/cloudinit/util.py
diff options
context:
space:
mode:
authorEmanuele Giuseppe Esposito <eesposit@redhat.com>2021-08-09 16:49:56 +0200
committerGitHub <noreply@github.com>2021-08-09 09:49:56 -0500
commit00dbaf1e9ab0e59d81662f0f3561897bef499a3f (patch)
tree6ff454c6b3acfad391f1c0c5424e6b592586f52c /cloudinit/util.py
parent13b6a8575f813699d406f5cab3424c2beffba26f (diff)
downloadcloud-init-git-00dbaf1e9ab0e59d81662f0f3561897bef499a3f.tar.gz
Stop copying ssh system keys and check folder permissions (#956)
In /etc/ssh/sshd_config, it is possible to define a custom authorized_keys file that will contain the keys allowed to access the machine via the AuthorizedKeysFile option. Cloudinit is able to add user-specific keys to the existing ones, but we need to be careful on which of the authorized_keys files listed to pick. Chosing a file that is shared by all user will cause security issues, because the owner of that key can then access also other users. We therefore pick an authorized_keys file only if it satisfies the following conditions: 1. it is not a "global" file, ie it must be defined in AuthorizedKeysFile with %u, %h or be in /home/<user>. This avoids security issues. 2. it must comply with ssh permission requirements, otherwise the ssh agent won't use that file. If it doesn't meet either of those conditions, write to ~/.ssh/authorized_keys We also need to consider the case when the chosen authorized_keys file does not exist. In this case, the existing behavior of cloud-init is to create the new file. We therefore need to be sure that the file complies with ssh permissions too, by setting: - the actual file to permission 600, and owned by the user - the directories in the path that do not exist must be root owned and with permission 755.
Diffstat (limited to 'cloudinit/util.py')
-rw-r--r--cloudinit/util.py51
1 files changed, 49 insertions, 2 deletions
diff --git a/cloudinit/util.py b/cloudinit/util.py
index d3ced463..c53f6453 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -35,6 +35,7 @@ from base64 import b64decode, b64encode
from errno import ENOENT
from functools import lru_cache
from urllib import parse
+from typing import List
from cloudinit import importer
from cloudinit import log as logging
@@ -1878,6 +1879,53 @@ def chmod(path, mode):
os.chmod(path, real_mode)
+def get_permissions(path: str) -> int:
+ """
+ Returns the octal permissions of the file/folder pointed by the path,
+ encoded as an int.
+
+ @param path: The full path of the file/folder.
+ """
+
+ return stat.S_IMODE(os.stat(path).st_mode)
+
+
+def get_owner(path: str) -> str:
+ """
+ Returns the owner of the file/folder pointed by the path.
+
+ @param path: The full path of the file/folder.
+ """
+ st = os.stat(path)
+ return pwd.getpwuid(st.st_uid).pw_name
+
+
+def get_group(path: str) -> str:
+ """
+ Returns the group of the file/folder pointed by the path.
+
+ @param path: The full path of the file/folder.
+ """
+ st = os.stat(path)
+ return grp.getgrgid(st.st_gid).gr_name
+
+
+def get_user_groups(username: str) -> List[str]:
+ """
+ Returns a list of all groups to which the user belongs
+
+ @param username: the user we want to check
+ """
+ groups = []
+ for group in grp.getgrall():
+ if username in group.gr_mem:
+ groups.append(group.gr_name)
+
+ gid = pwd.getpwnam(username).pw_gid
+ groups.append(grp.getgrgid(gid).gr_name)
+ return groups
+
+
def write_file(
filename,
content,
@@ -1904,8 +1952,7 @@ def write_file(
if preserve_mode:
try:
- file_stat = os.stat(filename)
- mode = stat.S_IMODE(file_stat.st_mode)
+ mode = get_permissions(filename)
except OSError:
pass