summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Olsson <andreas.olsson@hivestreaming.com>2017-07-19 17:30:12 +0200
committerjctanner <tanner.jc@gmail.com>2017-07-19 11:30:12 -0400
commit593297d7a220a33c5f8a8200e1f24071f9b051b5 (patch)
treeba627e5ce9a1bc656cf82e0667734d2de19a86cb
parent779d05aec413cf775bc9a388e7ac1fffad7e54d7 (diff)
downloadansible-593297d7a220a33c5f8a8200e1f24071f9b051b5.tar.gz
Only use `git verify-tag` when verifying annotated tags (#26414)
* Only use `git verify-tag` when verifying annotated tags The command `git verify-tag` only applies to annotated tags. When verifying lightweight tags, which are more similar to non-moving branches, one has to use `git verify-commit` instead. Using ':' as a separator is appropriate since that is one of the characters not allowed in a Git reference name. See also https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html * Improve testing of the Git module's gpg verification
-rw-r--r--lib/ansible/modules/source_control/git.py10
-rw-r--r--test/integration/targets/git/tasks/gpg-verification.yml187
-rw-r--r--test/integration/targets/git/tasks/main.yml6
-rw-r--r--test/integration/targets/git/tasks/tag-verification.yml57
-rw-r--r--test/integration/targets/git/vars/main.yml51
5 files changed, 248 insertions, 63 deletions
diff --git a/lib/ansible/modules/source_control/git.py b/lib/ansible/modules/source_control/git.py
index 3624c135a3..424761e9a1 100644
--- a/lib/ansible/modules/source_control/git.py
+++ b/lib/ansible/modules/source_control/git.py
@@ -590,15 +590,17 @@ def get_branches(git_path, module, dest):
return branches
-def get_tags(git_path, module, dest):
+def get_annotated_tags(git_path, module, dest):
tags = []
- cmd = '%s tag' % (git_path,)
+ cmd = [git_path, 'for-each-ref', 'refs/tags/', '--format', '%(objecttype):%(refname:short)']
(rc, out, err) = module.run_command(cmd, cwd=dest)
if rc != 0:
module.fail_json(msg="Could not determine tag data - received %s" % out, stdout=out, stderr=err)
for line in to_native(out).split('\n'):
if line.strip():
- tags.append(line.strip())
+ tagtype, tagname = line.strip().split(':')
+ if tagtype == 'tag':
+ tags.append(tagname)
return tags
@@ -887,7 +889,7 @@ def switch_version(git_path, module, dest, remote, version, verify_commit, depth
def verify_commit_sign(git_path, module, dest, version):
- if version in get_tags(git_path, module, dest):
+ if version in get_annotated_tags(git_path, module, dest):
git_sub = "verify-tag"
else:
git_sub = "verify-commit"
diff --git a/test/integration/targets/git/tasks/gpg-verification.yml b/test/integration/targets/git/tasks/gpg-verification.yml
new file mode 100644
index 0000000000..4fad418f7f
--- /dev/null
+++ b/test/integration/targets/git/tasks/gpg-verification.yml
@@ -0,0 +1,187 @@
+---
+# Test for verification of GnuPG signatures
+
+- name: Create GnuPG verification workdir
+ tempfile:
+ state: directory
+ register: git_gpg_workdir
+
+- name: Define variables based on workdir
+ set_fact:
+ git_gpg_keyfile: "{{ git_gpg_workdir.path }}/testkey.asc"
+ git_gpg_source: "{{ git_gpg_workdir.path }}/source"
+ git_gpg_dest: "{{ git_gpg_workdir.path }}/dest"
+ git_gpg_gpghome: "{{ git_gpg_workdir.path }}/gpg"
+
+- name: Temporary store GnuPG test key
+ copy:
+ content: "{{ git_gpg_testkey }}"
+ dest: "{{ git_gpg_keyfile }}"
+
+- name: Create temporary GNUPGHOME directory
+ file:
+ path: "{{ git_gpg_gpghome }}"
+ state: directory
+ mode: 0700
+
+- name: Import GnuPG test key
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ command: gpg --import {{ git_gpg_keyfile }}
+
+- name: Create local GnuPG signed repository directory
+ file:
+ path: "{{ git_gpg_source }}"
+ state: directory
+
+- name: Generate local GnuPG signed repository
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ shell: |
+ set -e
+ git init
+ touch an_empty_file
+ git add an_empty_file
+ git commit --no-gpg-sign --message "Commit, and don't sign"
+ git tag lightweight_tag/unsigned_commit HEAD
+ git commit --allow-empty --gpg-sign --message "Commit, and sign"
+ git tag lightweight_tag/signed_commit HEAD
+ git tag --annotate --message "This is not a signed tag" unsigned_annotated_tag HEAD
+ git commit --allow-empty --gpg-sign --message "Commit, and sign"
+ git tag --sign --message "This is a signed tag" signed_annotated_tag HEAD
+ git checkout -b some_branch/signed_tip master
+ git commit --allow-empty --gpg-sign --message "Commit, and sign"
+ git checkout -b another_branch/unsigned_tip master
+ git commit --allow-empty --no-gpg-sign --message "Commit, and don't sign"
+ git checkout master
+ args:
+ chdir: "{{ git_gpg_source }}"
+
+- name: Get hash of an unsigned commit
+ command: git show-ref --hash --verify refs/tags/lightweight_tag/unsigned_commit
+ args:
+ chdir: "{{ git_gpg_source }}"
+ register: git_gpg_unsigned_commit
+
+- name: Get hash of a signed commit
+ command: git show-ref --hash --verify refs/tags/lightweight_tag/signed_commit
+ args:
+ chdir: "{{ git_gpg_source }}"
+ register: git_gpg_signed_commit
+
+- name: Clone repo and verify signed HEAD
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ verify_commit: yes
+
+- name: Clone repo and verify a signed lightweight tag
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: lightweight_tag/signed_commit
+ verify_commit: yes
+
+- name: Clone repo and verify an unsigned lightweight tag (should fail)
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: lightweight_tag/unsigned_commit
+ verify_commit: yes
+ register: git_verify
+ ignore_errors: yes
+
+- name: Check that unsigned lightweight tag verification failed
+ assert:
+ that:
+ - git_verify|failed
+ - git_verify.msg|match("Failed to verify GPG signature of commit/tag.+")
+
+- name: Clone repo and verify a signed commit
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: "{{ git_gpg_signed_commit.stdout }}"
+ verify_commit: yes
+
+- name: Clone repo and verify an unsigned commit
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: "{{ git_gpg_unsigned_commit.stdout }}"
+ verify_commit: yes
+ register: git_verify
+ ignore_errors: yes
+
+- name: Check that unsigned commit verification failed
+ assert:
+ that:
+ - git_verify|failed
+ - git_verify.msg|match("Failed to verify GPG signature of commit/tag.+")
+
+- name: Clone repo and verify a signed annotated tag
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: signed_annotated_tag
+ verify_commit: yes
+
+- name: Clone repo and verify an unsigned annotated tag (should fail)
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: unsigned_annotated_tag
+ verify_commit: yes
+ register: git_verify
+ ignore_errors: yes
+
+- name: Check that unsigned annotated tag verification failed
+ assert:
+ that:
+ - git_verify|failed
+ - git_verify.msg|match("Failed to verify GPG signature of commit/tag.+")
+
+- name: Clone repo and verify a signed branch
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: some_branch/signed_tip
+ verify_commit: yes
+
+- name: Clone repo and verify an unsigned branch (should fail)
+ environment:
+ - GNUPGHOME: "{{ git_gpg_gpghome }}"
+ git:
+ repo: "{{ git_gpg_source }}"
+ dest: "{{ git_gpg_dest }}"
+ version: another_branch/unsigned_tip
+ verify_commit: yes
+ register: git_verify
+ ignore_errors: yes
+
+- name: Check that unsigned branch verification failed
+ assert:
+ that:
+ - git_verify|failed
+ - git_verify.msg|match("Failed to verify GPG signature of commit/tag.+")
+
+- name: Remove GnuPG verification workdir
+ file:
+ path: "{{ git_gpg_workdir.path }}"
+ state: absent
diff --git a/test/integration/targets/git/tasks/main.yml b/test/integration/targets/git/tasks/main.yml
index bc87aeb810..6d776fc692 100644
--- a/test/integration/targets/git/tasks/main.yml
+++ b/test/integration/targets/git/tasks/main.yml
@@ -27,7 +27,11 @@
- include: change-repo-url.yml
- include: depth.yml
- include: checkout-new-tag.yml
-- include: tag-verification.yml
+- include: gpg-verification.yml
+ when: >
+ not gpg_version.stderr and
+ gpg_version.stdout and
+ git_version.stdout | version_compare("2.1.0", '>=')
- include: localmods.yml
- include: reset-origin.yml
- include: ambiguous-ref.yml
diff --git a/test/integration/targets/git/tasks/tag-verification.yml b/test/integration/targets/git/tasks/tag-verification.yml
deleted file mode 100644
index 6bd06b87e1..0000000000
--- a/test/integration/targets/git/tasks/tag-verification.yml
+++ /dev/null
@@ -1,57 +0,0 @@
----
- # Test for tag verification
- # clone a repo checkout signed tag, verify tag
-
-- name: Import Jamie Evans GPG key
- command: gpg --keyserver keyserver.ubuntu.com --recv-key 61107C8E
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: Copy ownertrust
- copy: "content='2D55902D66FEEBCEA4447C93E79A36DA61107C8E:6:\n' dest=/tmp/ownertrust-git.txt"
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: Import ownertrust
- command: gpg --import-ownertrust /tmp/ownertrust-git.txt
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: Clone signed repo and verify tag
- git: repo={{ repo_verify }} dest={{ checkout_dir }} version=v0.0 verify_commit=yes
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: Remove Jamie Evans GPG key
- command: gpg --batch --yes --delete-key 61107C8E
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: Clean up files
- file: path="{{ item }}" state=absent
- with_items:
- - "{{ checkout_dir }}"
- - /tmp/ownertrust-git.txt
- when: >
- not gpg_version.stderr and
- gpg_version.stdout and
- (git_version.stdout | version_compare("2.1.0", '>=') or
- gpg_version.stdout | version_compare("1.4.16", '>='))
-
-- name: clear checkout_dir
- file: state=absent path={{ checkout_dir }}
diff --git a/test/integration/targets/git/vars/main.yml b/test/integration/targets/git/vars/main.yml
index f4364bc481..2c6212fffd 100644
--- a/test/integration/targets/git/vars/main.yml
+++ b/test/integration/targets/git/vars/main.yml
@@ -12,7 +12,6 @@ repo_submodule1_newer: 'https://github.com/abadger/test_submodules_subm1_newer.g
repo_submodule2: 'https://github.com/abadger/test_submodules_subm2.git'
repo_update_url_1: 'https://github.com/ansible-test-robinro/git-test-old'
repo_update_url_2: 'https://github.com/ansible-test-robinro/git-test-new'
-repo_verify: 'https://github.com/pixelrebel/ansible-git-test.git'
known_host_files:
- "{{ lookup('env','HOME') }}/.ssh/known_hosts"
- '/etc/ssh/ssh_known_hosts'
@@ -20,3 +19,53 @@ git_version_supporting_depth: 1.9.1
git_version_supporting_ls_remote: 1.7.5
# path to a SSH private key for use with github.com (tests skipped if undefined)
# github_ssh_private_key: "{{ lookup('env', 'HOME') }}/.ssh/id_rsa"
+git_gpg_testkey: |
+ -----BEGIN PGP PRIVATE KEY BLOCK-----
+
+ lQOYBFlkmX0BCACtE81Xj/351nnvwnAWMf8ZUP9B1YOPe9ohqNsCQY1DxODVJc9y
+ ljCoh9fTdoHXuaUMUFistozxCMP81RuZxfbfsGePnl8OAOgWT5Sln6yEG45oClJ0
+ RmJJZdDT1lF3VaVwK9NQ5E1oqmk1IOjISi7iFa9TmMn1h7ISP/p+/xtMxQhzUXt8
+ APAEhRdc9FfwxaxCHKZBiM7ND+pAm6vpom07ZUgxSppsrXZAxDncTwAeCumDpeOL
+ LAcSBsw02swOIHFfqHNrkELLr4KJqws+zeAk6R2nq0k16AVdNX+Rb7T3OKmuLawx
+ HXe8rKpaw0RC+JCogZK4tz0KDNuZPLW2Y5JJABEBAAEAB/4zkKpFk79p35YNskLd
+ wgCMRN7/+MKNDavUCnBRsEELt0z7BBxVudx+YZaSSITvxj4fuJJqxqqgJ2no2n8y
+ JdJjG7YHCnqse+WpvAUAAV4PL/ySD704Kj4fOwfoDTrRUIGNNWlseNB9RgQ5UXg5
+ MCzeq/JD+En3bnnFySzzCENUcAQfu2FVYgKEiKaKL5Djs6p5w/jTm+Let3EsIczb
+ ykJ8D4/G/tSrNdp/g10DDy+VclWMhMFqmFesedvytE8jzCVxPKOoRkFTGrX76gIK
+ eMVxHIYxdCfSTHLjBykMGO9gxfk9lf18roNYs0VV2suyi4fVFxEozSAxwWlwKrXn
+ 0arvBADPsm5NjlZ5uR06YKbpUUwPTYcwLbasic0qHuUWgNsTVv8dd2il/jbha77m
+ StU7qRJ1jwbFEFxx7HnTmeGfPbdyKe2qyLJUyD/rpQSC5YirisUchtG8nZsHlnzn
+ k10SIeB480tkgkdMQx1Eif40aiuQb09/TxaaXAEFKttZhEO4RwQA1VQ8a0IrMBI2
+ i4WqaIDNDl3x61JvvFD74v43I0AHKmZUPwcgAd6q2IvCDaKH0hIuBKu6BGq6DPvx
+ Oc/4r3iRn/xccconxRop2A9ffa00B/eQXrBq+uLBQfyiFL9UfkU8eTAAgbDKRxjY
+ ScaevoBbbYxkpgJUCL6VnoSdXlbNOO8EAL2ypsVkDmXNgR8ZT8cKSUft47di5T+9
+ mhT1qmD62B+D86892y2QAohmUDadYRK9m9WD91Y7gOMeNhYj9qbxyPprPYUL0aPt
+ L8KS1H73C5WQMOsl2RyIw81asss30LWghsFIJ1gz8gVEjXhV+YC6W9XQ42iabmRR
+ A67f5sqK1scuO0q0KUFuc2libGUgVGVzdCBSdW5uZXIgPG5vcmVwbHlAZXhhbXBs
+ ZS5jb20+iQE3BBMBCAAhBQJZZJl9AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheA
+ AAoJEK0vcLBcXpbYi/kH/R0xk42MFpGd4pndTAsVIjRk/VhmhFc1v6sBeR40GXlt
+ hyEeOQQnIeHKLhsVT6YnfFZa8b4JwgTD6NeIiibOAlLgaKOWNwZu8toixMPVAzfQ
+ cRei+/gFXNil0FmBwWreVBDppuIn6XiSEPik0C7eCcw4lD+A+BbL3WGkp+OSQPho
+ hodIU02hgkrgs/6YJPats8Rgzw9hICsa2j0MjnG6P2z9atMz6tw2SiE5iBl7mZ2Z
+ zG/HiplleMhf/G8OZOskrWkKiLbpSPfQSKdOFkw1C6yqOlQ+HmuCZ56oyxtpItET
+ R11uAKt+ABdi4DX3FQQ+A+bGJ1+aKrcorZ8Z8s0XhPo=
+ =tV71
+ -----END PGP PRIVATE KEY BLOCK-----
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+
+ mQENBFlkmX0BCACtE81Xj/351nnvwnAWMf8ZUP9B1YOPe9ohqNsCQY1DxODVJc9y
+ ljCoh9fTdoHXuaUMUFistozxCMP81RuZxfbfsGePnl8OAOgWT5Sln6yEG45oClJ0
+ RmJJZdDT1lF3VaVwK9NQ5E1oqmk1IOjISi7iFa9TmMn1h7ISP/p+/xtMxQhzUXt8
+ APAEhRdc9FfwxaxCHKZBiM7ND+pAm6vpom07ZUgxSppsrXZAxDncTwAeCumDpeOL
+ LAcSBsw02swOIHFfqHNrkELLr4KJqws+zeAk6R2nq0k16AVdNX+Rb7T3OKmuLawx
+ HXe8rKpaw0RC+JCogZK4tz0KDNuZPLW2Y5JJABEBAAG0KUFuc2libGUgVGVzdCBS
+ dW5uZXIgPG5vcmVwbHlAZXhhbXBsZS5jb20+iQE3BBMBCAAhBQJZZJl9AhsDBQsJ
+ CAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEK0vcLBcXpbYi/kH/R0xk42MFpGd4pnd
+ TAsVIjRk/VhmhFc1v6sBeR40GXlthyEeOQQnIeHKLhsVT6YnfFZa8b4JwgTD6NeI
+ iibOAlLgaKOWNwZu8toixMPVAzfQcRei+/gFXNil0FmBwWreVBDppuIn6XiSEPik
+ 0C7eCcw4lD+A+BbL3WGkp+OSQPhohodIU02hgkrgs/6YJPats8Rgzw9hICsa2j0M
+ jnG6P2z9atMz6tw2SiE5iBl7mZ2ZzG/HiplleMhf/G8OZOskrWkKiLbpSPfQSKdO
+ Fkw1C6yqOlQ+HmuCZ56oyxtpItETR11uAKt+ABdi4DX3FQQ+A+bGJ1+aKrcorZ8Z
+ 8s0XhPo=
+ =mUYY
+ -----END PGP PUBLIC KEY BLOCK-----