50

While doing clone, push or pull of a private git repository hosted internally (e.g. on a GitLab instance) with Ansible's Git module, how do I specify username and password to authenticate with the Git server?

I don't see any way to do this in the documentation.

karthik v
  • 1,104
  • 1
  • 14
  • 22

5 Answers5

67

You can use something like this:

---
- hosts: all 
  gather_facts: no
  become: yes
  tasks:
    - name: install git package
      apt:
        name: git

    - name: Get updated files from git repository 
      git: 
        repo: "https://{{ githubuser | urlencode }}:{{ githubpassword | urlencode }}@github.com/privrepo.git"
        dest: /tmp

Note: {{ githubpassword | urlencode }} is used here, if your password also contains special characters @,#,$ etc

Then execute the following playbook:

ansible-playbook -i hosts github.yml -e "githubuser=arbabname" -e "githubpassword=xxxxxxx"

Note: Make sure you put the credentials in ansible vaults or pass it secure way

Tara Prasad Gurung
  • 3,422
  • 6
  • 38
  • 76
Arbab Nazar
  • 22,378
  • 10
  • 76
  • 82
  • 3
    This doesn't work if there are certain special characters, e.g. `!` in the password. – StockB Jul 15 '16 at 19:15
  • 3
    @StockB I have updated the answer please check it now with `urlencode` filter – Arbab Nazar Jul 16 '16 at 15:49
  • 5
    BTW you can generate token and use it instead of password. You can create token without admin rights and you can revoke it at any time. And token never contains symbols which you need to urlencode. – Vadym Apr 27 '17 at 09:00
  • 1
    @Vadym you are right but here questioner ask about that how he/she can pass the username/password not the token. Thanks – Arbab Nazar Apr 27 '17 at 11:27
  • My password contained ```@``` so i had to use urlencode for password as well – Shrikant Shete Sep 17 '17 at 20:50
  • Is there any reason to *not* just always urlencode the password then? – Nik Reiman Oct 16 '17 at 08:13
  • 1
    As pointed out by the answer of @marco-eckstein, this approach results in the password being stored in plain text in the `.git/config` file of the working copy. Use a different method if you do not want to leak your credentials to the target machine. – leopold.talirz Sep 19 '22 at 13:33
40

Improving on Arbab Nazar's answer, you can avoid exposing your password in the terminal by prompting for the credentials.

playbook.yml

--- 
- name: ANSIBLE - Shop Installation 
  hosts: '{{ target }}' 

  vars_prompt: 
    - name: "githubuser" 
      prompt: "Enter your github username" 
      private: no 
    - name: "githubpassword" 
      prompt: "Enter your github password" 
      private: yes 

  [...] 

And in the task reference the variables.

task.yml

- name: Get updated files from git repository 
  git:
    repo=https://{{ githubuser | urlencode }}:{{ githubpassword | urlencode }}@github.com/privrepo.git
    dest=/tmp

This will save the password as clear text in .git/config as url of remote "origin". The following task can be used to remove it.

- name: Ensure remote URL does not contain credentials
  git_config:
    name: remote.origin.url
    value: https://github.com/privrepo.git
    scope: local
    repo: /tmp

Taken from: Clone a private git repository with Ansible (using password prompt)

gillesB
  • 1,061
  • 1
  • 14
  • 30
F. Santiago
  • 842
  • 10
  • 18
  • 5
    this is also exposing username/password (the remote origin stored as `https://user:password@github.com/...`) – Valentin Kantor Jun 10 '18 at 00:13
  • 3
    You cannot avoid exposing the token or password. Git writes it to .git/config. Check here for more details, https://help.github.com/en/articles/git-automation-with-oauth-tokens. – Hieu Feb 27 '19 at 04:15
16

While Arbab's and F. Santiago's answers are correct, there is an important caveat: With https://{{ githubuser | urlencode }}:{{ githubpassword | urlencode }}@github.com/privrepo.git as the checkout URL, Git will store your password in plaintext inside the .git/ folder. This has been mentioned in a comment, but I think it deserves more attention. You might want to do away the Git module and use raw Git, e.g.:

vars_prompt: 
  - name: "githubuser" 
    prompt: "Enter your github username" 
    private: no 
  - name: "githubpassword" 
    prompt: "Enter your github password" 
    private: yes
tasks:
  - name: Git clone
    expect:
      command: git clone https://github.com/privrepo.git /tmp
      responses:
        Username: "{{ githubuser }}" # Username is a regex
        Password: "{{ githubpassword }}" # Password is a regex
    no_log: true
Marco Eckstein
  • 4,448
  • 4
  • 37
  • 48
  • What do you mean by username/password "is a regex"? – trebor Dec 14 '20 at 02:14
  • @trebor By "Username is a regex" he means that where you see "Username:" at the start of the line he is supplying a regular expression that the expect module will match against stdout to determine whether to respond by supplying the corresponding value to stdin. – Will Feb 22 '21 at 03:41
  • It's for sure important to be aware that Git will store your password in plaintext. but for me is not that critical because I have I use a deploy token that is read-only that I can frequently change. Thank you – Rizerzero Jan 31 '22 at 13:12
4

All of the answers here made it a bit too easy to leak the username/password into a log or error message, which seemed undesirable even if in my case it's a read-only deployment token.

Here's an alternative:

    - name: Configure Git credential storage
      command: "git config --global credential.helper store"
    - name: Populate the Git credential store
      template:
        src: files/git_credentials.j2
        dest: /home/appuser/.git-credentials
        owner: appuser
        group: appuser
        mode: u=rw,g=,o=
      no_log: true

The template looks like this:

https://{{ gitlab_username|urlencode }}:{{ gitlab_password|urlencode }}@gitlab.example.org
Chris Adams
  • 4,966
  • 1
  • 30
  • 28
2

If you prefer non-interactive mode, there are (at least) two options:

  1. Temporarily upload .netrc
$ cat ~/.netrc
machine github.com login martin.pilka password PASSWORD

$ cat playbook.yaml
...
    - name: Temporarily copy .netrc so "git clone" below works without asking for password
      ansible.builtin.copy:
        src: ~/.netrc
        dest: ./
        mode: "u=rw,g=rw,o="

    - name: Clone repo so remote changes can be easily committed
      ansible.builtin.git:
        repo: https://martin.pilka@github.com/dNationCloud/kubernetes-monitoring
        dest: git/kubernetes-monitoring/
        clone: yes
        update: yes

    - name: Securely delete .netrc
      command: shred --iterations=1 --remove ~/.netrc
      args:
        removes: ~/.netrc

  1. Use Ansible Vault
$ cat playbook.yaml
...
    - name: Clone repo so remote changes can be easily committed
      vars:
        # Encrypted URL including password:
        # https://martin.pilka:PASSWORD@github.com/dNationCloud/kubernetes-monitoring
        repo: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          ...
      ansible.builtin.git:
        repo: "{{ repo }}"
        dest: git/kubernetes-monitoring/
        clone: yes
        update: yes

    - name: Remove credentials from GIT URL
      ansible.builtin.git_config:
        name: remote.origin.url
        value: https://martin.pilka@github.com/dNationCloud/kubernetes-monitoring
        scope: local
        repo: git/kubernetes-monitoring/

Notes:

  • Option 1 is simpler - no need to use Ansible Vault related commands/parameters (when encoding secret and playing book)
  • Unfortunately both options temporarily store password on remote side in plain text (in .netrc or .git/config) - same is true for all other solutions listed here
Martin
  • 107
  • 1
  • 3