Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework clone #289

Merged
merged 3 commits into from
Feb 6, 2021
Merged

Rework clone #289

merged 3 commits into from
Feb 6, 2021

Conversation

erijo
Copy link
Contributor

@erijo erijo commented Jan 2, 2021

What does this PR do?

This PR changes the way clone works to use git clone instead of init+config+fetch+merge. I've also changed the default behavior to leave local changes in the working copy.

What issues does this PR fix or reference?

None

Previous Behavior

See above.

New Behavior

See above.

Have tests been written for this change?

No, but existing tests have been updated.

Have these commits been signed with GnuPG?

Yes


Please review yadm's Contributing Guide for best practices.

@TheLocehiliosan
Copy link
Owner

I'm not able to review this closely right now, but I can say I did look at making a similar change in the past few months, and there was some reasons that pushed me away from it. And until I get into it, I don't think I'm going to recall. I think it may have had something to do with previous concerns about exposed directories (ssh/gnupg). That is, if someone manages configs that are inside those directories, I need to be sure that those directories are not made readable at any point (even for a split second). Also, the data managed in them is part of the repo, so the repo itself also needs to be secured. Git (I believe) uses the same perms for everything based on the umask. One advantage of doing the init then merge is you can secure those directories (including the repo) before any of the repo's data arrives at the computer.

Again, I will watch your development with interest, but just so you know, I think that's background. There was a CVE logged against this project, and I had to scramble to to have it resolved (and it didn't matter how valid the CVE was). I will not make a change if I think it will open the project to something similar again.

@erijo
Copy link
Contributor Author

erijo commented Jan 2, 2021

I've looked into the permissions a bit. First, below is a part of the strace output when running git init --shared=0600 --bare repo.git:

[...]
150575 mkdir("repo.git", 0777)          = 0
[a lot of calls related to copying /usr/share/git-core/templates removed]
150575 chmod("/home/erik/tmp/yadm/repo.git", 02700) = 0
150575 mkdir("/home/erik/tmp/yadm/repo.git/refs", 0777) = 0
[...]
150575 mkdir("/home/erik/tmp/yadm/repo.git/objects", 0777) = 0
150575 chmod("/home/erik/tmp/yadm/repo.git/objects", 02700) = 0

I.e. the permissions for repo.git is set to the shared mode 02700 early on, before the objects dir is created. We can compare this with the strace output from git -c core.sharedrepository=0600 clone --separate-git-dir repo.git --no-checkout <url>:

[...]
149595 mkdir("/home/erik/tmp/yadm/repo.git", 0777) = 0
[a lot of calls related to copying /usr/share/git-core/templates removed]
149595 chmod("/home/erik/tmp/yadm/repo.git", 02700) = 0
149595 mkdir("/home/erik/tmp/yadm/repo.git/refs", 0777) = 0
[...]
149595 mkdir("/home/erik/tmp/yadm/repo.git/objects", 0777) = 0
149595 chmod("/home/erik/tmp/yadm/repo.git/objects", 02700) = 0
[...]
149596 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3

The calls related to the repo.git dir is very similar for both init and clone. In both cases the permissions are changed before anything is written to it. In the clone case we can e.g. see that opening the ssh socket is done after the permissions have been set.

If we look at the source code for git init it calls init_db at the end. This is also called from git clone. init_db calls create_default_files which does copy_templates() before doing adjust_shared_perm(get_git_dir()) followed by safe_create_dir(git_path("refs"), 1). So the calls seen in strace matches the code :)

Based on this I think the security should be as good as with the init variant.

@erijo erijo force-pushed the clone branch 5 times, most recently from b8e7143 to 2e0ae21 Compare January 3, 2021 10:11
@erijo erijo changed the title WIP: Rework clone Rework clone Jan 3, 2021
@erijo erijo force-pushed the clone branch 2 times, most recently from 8c82f15 to 55191a8 Compare January 3, 2021 22:23
@erijo
Copy link
Contributor Author

erijo commented Jan 3, 2021

This is no longer a WIP. I've done the things I wanted to do.

@erijo
Copy link
Contributor Author

erijo commented Jan 7, 2021

I'll rebase this later to fix the conflict and correct the zsh completion change.

Instead of doing work to find the default branch just to be able to
set up the repository before doing a fetch, do a "git clone" and let
git handle it.

Use -c core.sharedrepository=0600 to get the same result as
--shared=0600 passed to init.

Use --separate-git-dir to get the git directory in $YADM_REPO. Use a
temporary dir as work tree and remove it right after the clone is
done.

When the clone is done, iterate over all missing files in $YADM_WORK
and perform a checkout. If local files exists that differ compared
with the cloned ones the local files are left intact and the user is
instructed to deal with the conflicts.
when forcing init/clone to happen.
@TheLocehiliosan TheLocehiliosan self-assigned this Feb 4, 2021
@TheLocehiliosan TheLocehiliosan added this to In progress in 3.1.0 via automation Feb 4, 2021
@TheLocehiliosan
Copy link
Owner

@erijo I had time today to go through all of these changes in detail. This is a really solid change. 👍 I make only a few edits on top of this, and pushed them into branch pr/289. Please confirm this looks good to you as well. Only real change is to remove the mktemp dependency. I had problems in the past with mktemp portability.

You're using a variable named "wc" and I'm sure there must be something obvious that stands for, but it isn't apparent to me. What does "wc" mean?

@TheLocehiliosan
Copy link
Owner

The only other item that I was curious about was how far back the --separate-git-dir option was introduced. It looks like that's available since Git 1.7.5. So while this change will bump the minimum supported version of Git, but that's a really old version of Git. 👍

@TheLocehiliosan
Copy link
Owner

One last bit of praise; I really do prefer this strategy where conflicting changes are left as modified working files.

Stashing them was a convenient way to deal with the inability to merge in the past, but it was confusing to some users that are not familiar with all of Git's features. Your strategy leaves the work tree intact and changes as clear diffs. I think this will make sense to most everyone.

@erijo
Copy link
Contributor Author

erijo commented Feb 4, 2021

Your changes look fine to me 👍

wc is short for working copy.

@TheLocehiliosan TheLocehiliosan merged commit 9c999c7 into TheLocehiliosan:develop Feb 6, 2021
3.1.0 automation moved this from In progress to Done Feb 6, 2021
@erijo erijo deleted the clone branch February 6, 2021 20:48
@erijo
Copy link
Contributor Author

erijo commented Feb 6, 2021

The documentation needs an update as well after this. Will you do that @TheLocehiliosan or should I put together a PR?

@TheLocehiliosan
Copy link
Owner

I do make an effort to give the docs (both manage and website) an update when I do a release for all the changes in the release. But help is always nice.

erijo added a commit to erijo/yadm that referenced this pull request Feb 8, 2021
@erijo erijo mentioned this pull request Feb 8, 2021
erijo added a commit to erijo/yadm that referenced this pull request Feb 8, 2021
erijo added a commit to erijo/yadm that referenced this pull request Feb 13, 2021
TheLocehiliosan added a commit that referenced this pull request Mar 22, 2021
* Use `git clone` directly during clone (#289, #323)
* Fix compatibility bug with Git completions (#318, #321)
* Support relative paths for --yadm-* and -w (#301)
* Improve parsing of if-statement in default template (#303)
* Read files without running cat in subshells (#317)
* Improve portability of updating read-only files (#320)
* Various code improvements (#306, #307, #311)
TheLocehiliosan added a commit that referenced this pull request Apr 3, 2021
* Use `git clone` directly during clone (#289, #323)
* Fix compatibility bug with Git completions (#318, #321)
* Support relative paths for --yadm-* and -w (#301)
* Improve parsing of if-statement in default template (#303)
* Read files without running cat in subshells (#317)
* Improve portability of updating read-only files (#320)
* Various code improvements (#306, #307, #311)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
3.1.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants