Skip to content

Fix home permissions modified by ssh module (SC-338)#984

Merged
TheRealFalcon merged 7 commits into
canonical:mainfrom
TheRealFalcon:ssh-home-perms
Aug 20, 2021
Merged

Fix home permissions modified by ssh module (SC-338)#984
TheRealFalcon merged 7 commits into
canonical:mainfrom
TheRealFalcon:ssh-home-perms

Conversation

@TheRealFalcon
Copy link
Copy Markdown
Contributor

Proposed Commit Message

Fix home permissions modified by ssh module

In #956, we updated the file and directory permissions for keys not in
the user's home directory. We also unintentionally modified the
permissions within the home directory as well. These should not change,
and this commit changes that back.

LP: #1940233

Additional Context

See #956 and https://bugs.launchpad.net/cloud-init/+bug/1940233

Test Steps

Checklist:

  • My code follows the process laid out in the documentation
  • I have updated or added any unit tests accordingly
  • I have updated or added any documentation accordingly

@TheRealFalcon
Copy link
Copy Markdown
Contributor Author

FYI @esposem

@TheRealFalcon TheRealFalcon changed the title Fix home permissions modified by ssh module Fix home permissions modified by ssh module (SC-338) Aug 17, 2021
In canonical#956, we updated the file and directory permissions for keys not in
the user's home directory. We also unintentionally modified the
permissions within the home directory as well. These should not change,
and this commit changes that back.

LP: #1940233
Comment thread cloudinit/ssh_util.py Outdated
gid = user_pwent.pw_gid
try:
os.mkdir(parent_folder, mode=mode)
except FileExistsError:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So with this change

  • /, /home/ and /home/<user> are skipped and not created in any case.
  • then, we can have either a path that is not in the user home folder, and we chmod it to root ownership, or inside the user folder, and we chmod it as user-owned.

Only one question: what if /home/ or /home/<user> do not exist? os.mkdir should launch a FileNotFoundError I think, we should handle also this case right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I agree with @paride in https://bugs.launchpad.net/cloud-init/+bug/1940233/comments/4 when he says it's not the responsibility of this module to create a user's home directory.

Copy link
Copy Markdown
Contributor

@paride paride Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of thoughts about this:

  • The authorized_keys file is always created user-owned (chmod 600), even if its path is outside the user's $HOME directory. I think this is good, so users are still be able to manage their own authorized_keys.
  • Given that we've got bitten by this, I think it we should test two more scenarios:
    • AuthorizedKeysFile outside of $HOME, e.g. in /etc/ssh/authorized_keys/%u/
    • AuthorizedKeysFile deeper in $HOME, e.g. %h/foo/bar/ssh/

Wydt?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheRealFalcon ok, seems reasonable
@paride regarding the right permission w.r.t. authorized_keys files, look here. The mistake in this code is that I did not think about the permissions that other ssh tools need, in this case ssh-keygen. Because if .ssh has permission 755 and it's owned by root, it should work w.r.t. AuthorizedKeysFile.

After a quick test I see that the mode doesn't matter, the ownership is the problem (which makes sense because with root owner and 755 ssh-keygen on behalf of the user cannot write in the folder).

Regarding the first scenario, it is covered in this and this test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the requested integration tests. There's some overlap with the unit tests (and the unit tests are much more comprehensive), but better to have a basic integration check of the other use cases too.

Copy link
Copy Markdown
Contributor

@esposem esposem Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thank you!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Comment thread cloudinit/ssh_util.py Outdated
parent_folder == user_pwent.pw_dir):
continue

if not os.path.isdir(parent_folder):
Copy link
Copy Markdown
Contributor

@paride paride Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one weird case that is not covered by this if: parent_folder existing but not-a-directory (file, symlink). In this case cloud-init is going to fail creating deeper subdirectories or the authorized_keys file, possibly doing unexpected things in the case of a symlink. Do you think we should cover this case, returning early when not os.path.isdir(parent_folder) but os.path.exists(parent_folder)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More specifically I'm worried by a user doing e.g. ln -s .ssh /root/.ssh, and of what would cloud-init do.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed 240a079 , which I think addresses this.

@TheRealFalcon
Copy link
Copy Markdown
Contributor Author

@esposem , Yep, my bad. I misread Paride's comment and went a direction based off a wrong assumption. What you say makes sense.

@esposem
Copy link
Copy Markdown
Contributor

esposem commented Aug 18, 2021

Everything now looks good to me, thank you for working on this!

assert '{} {}'.format(user, home_perms) == client.execute(
'stat -c "%U %a" {}'.format(home_dir)
)
if client.execute("test -f {}/.ssh".format(home_dir)).ok:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually work? I get exit 1 from this call meaning we don't drop in for the perms check.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also can we attempt to run something like the example ssh-keygen call in the bug report to confirm that all the plumbing works as expected without error?

Copy link
Copy Markdown
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Needs rebase and CI pass but otherwise +1

@TheRealFalcon TheRealFalcon merged commit 7d3f5d7 into canonical:main Aug 20, 2021
@TheRealFalcon TheRealFalcon deleted the ssh-home-perms branch August 20, 2021 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants