Best way to clone a git repository when authenticating via ssh key forwarding
- Host & git authentication happens via ssh key
- ssh key forwarding is enabled
- Every user of our team uses a dedicated user account – it is not possible to log in via headless user account
Now we want to deploy an application from a git repository. This should be simple but it’s not.
- name: Clone app repo git: repo: githost:org/repo.git dest: /some/location version: HEAD force: yes ssh_opts: -o StrictHostKeyChecking=no notify: - Restart app
githost is an entry in our .ssh/config
This above task works. But the repository is (of course) cloned as the user who executed the playbook. What we need instead is:
- All files should be owned by a headless user, let’s call him
zaphodis allowed to read the files. We’re talking about 0600/0700 permissions.
The following task will not work, because by using
become we will lose the forwarded ssh key and therefore git authentication will fail:
- name: Clone app repo git: repo: githost:org/repo.git dest: /some/location version: HEAD force: yes ssh_opts: -o StrictHostKeyChecking=no notify: - Restart app become: yes become_user: zaphod
The following variation would first call a handler which changes ownership of the checkout before (re)starting the application:
- name: Clone app repo git: repo: githost:org/repo.git dest: /some/location version: HEAD force: yes ssh_opts: -o StrictHostKeyChecking=no notify: - Fix ownership - Restart app
This works once. But if you run the playbook a 2nd time the git task fails because the user who runs the play does not have permissions to modify the clone.
We have a very ugly solution:
- Clone into /tmp/foo
- Fix ownership of /tmp/foo
rm -rf /some/location
mv /tmp/foo /some/location
- Finally (re)start application
The problem with this is that this would:
- Trigger a restart every single time the playbook is executed
- The Ansible summary shows 5 changed tasks, even though nothing happened – except the restart which was not required in the first place
I’m a bit picky here, but I do only want to have changed states if something really changed, so in a perfect world not even the git task would have a changed state. And for this I do not see a solution. Because we require that the cloned files are only accessible by
zaphod – but
zaphod himself is not able to clone the repo. So there has to be some manipulation is some form resulting in changes.
Any suggestions how this can be improved in a clean way? I don’t want to add another 20 tasks shuffling around with temporary copies, temporarily changing permissions, comparing files manually and so forth…
Of course a custom written module would be able to deal with all this – but I’m more interested in something that does not take 2 days in development and battle testing. 😉
One Solution collect form web for “Best way to clone a git repository when authenticating via ssh key forwarding”
It looks like you’re trying to deploy an application/webpage by simply cloning the repo containing the stuff you need rather than needing to be able to then push any changes back to the repo from that server.
If that’s the case then you could get away with a local task to
git archive the repo into a tarball or something and then use
unarchive to copy the resulting archive to the target machine and unpack it.
unarchive will allow you to set the permissions and ownership.
So your play could look something like:
- name: locally clone repo git: repo: githost:org/repo.git dest: /some/tmp/location version: HEAD force: yes delegate_to: localhost changed_when: false # - name: archive app repo command: git archive --format zip --output /path/to/archive master chdir: /some/tmp/location delegate_to: localhost changed_when: false - name: unarchive app repo unarchive: src: /path/to/archive dest: /some/location owner: zaphod mode: 0700 creates: /some/location notify: - Restart app