1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Added SHA1 option to maven_artifact (#2662)

* Added SHA1 option

* Add changelog fragment

* Update plugins/modules/packaging/language/maven_artifact.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/packaging/language/maven_artifact.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Combined hash functions

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/packaging/language/maven_artifact.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/packaging/language/maven_artifact.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Removed unused functions (rolled into _local_checksum)

* Update changelogs/fragments/2661-maven_artifact-add-sha1-option.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Gene Gotimer 2021-06-01 16:06:26 -04:00 committed by GitHub
parent 1ad85849af
commit ca1506fb26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 28 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- maven_artifact - added ``checksum_alg`` option to support SHA1 checksums in order to support FIPS systems (https://github.com/ansible-collections/community.general/pull/2662).

View file

@ -129,10 +129,10 @@ options:
verify_checksum:
type: str
description:
- If C(never), the md5 checksum will never be downloaded and verified.
- If C(download), the md5 checksum will be downloaded and verified only after artifact download. This is the default.
- If C(change), the md5 checksum will be downloaded and verified if the destination already exist,
to verify if they are identical. This was the behaviour before 2.6. Since it downloads the md5 before (maybe)
- If C(never), the MD5/SHA1 checksum will never be downloaded and verified.
- If C(download), the MD5/SHA1 checksum will be downloaded and verified only after artifact download. This is the default.
- If C(change), the MD5/SHA1 checksum will be downloaded and verified if the destination already exist,
to verify if they are identical. This was the behaviour before 2.6. Since it downloads the checksum before (maybe)
downloading the artifact, and since some repository software, when acting as a proxy/cache, return a 404 error
if the artifact has not been cached yet, it may fail unexpectedly.
If you still need it, you should consider using C(always) instead - if you deal with a checksum, it is better to
@ -141,6 +141,15 @@ options:
required: false
default: 'download'
choices: ['never', 'download', 'change', 'always']
checksum_alg:
type: str
description:
- If C(md5), checksums will use the MD5 algorithm. This is the default.
- If C(sha1), checksums will use the SHA1 algorithm. This can be used on systems configured to use
FIPS-compliant algorithms, since MD5 will be blocked on such systems.
default: 'md5'
choices: ['md5', 'sha1']
version_added: 3.2.0
directory_mode:
type: str
description:
@ -507,7 +516,7 @@ class MavenDownloader:
raise ValueError(failmsg + " because of " + info['msg'] + "for URL " + url_to_use)
return None
def download(self, tmpdir, artifact, verify_download, filename=None):
def download(self, tmpdir, artifact, verify_download, filename=None, checksum_alg='md5'):
if (not artifact.version and not artifact.version_by_spec) or artifact.version == "latest":
artifact = Artifact(artifact.group_id, artifact.artifact_id, self.find_latest_version_available(artifact), None,
artifact.classifier, artifact.extension)
@ -528,11 +537,11 @@ class MavenDownloader:
shutil.copyfileobj(response, f)
if verify_download:
invalid_md5 = self.is_invalid_md5(tempname, url)
if invalid_md5:
invalid_checksum = self.is_invalid_checksum(tempname, url, checksum_alg)
if invalid_checksum:
# if verify_change was set, the previous file would be deleted
os.remove(tempname)
return invalid_md5
return invalid_checksum
except Exception as e:
os.remove(tempname)
raise e
@ -541,40 +550,45 @@ class MavenDownloader:
shutil.move(tempname, artifact.get_filename(filename))
return None
def is_invalid_md5(self, file, remote_url):
def is_invalid_checksum(self, file, remote_url, checksum_alg='md5'):
if os.path.exists(file):
local_md5 = self._local_md5(file)
local_checksum = self._local_checksum(checksum_alg, file)
if self.local:
parsed_url = urlparse(remote_url)
remote_md5 = self._local_md5(parsed_url.path)
remote_checksum = self._local_checksum(checksum_alg, parsed_url.path)
else:
try:
remote_md5 = to_text(self._getContent(remote_url + '.md5', "Failed to retrieve MD5", False), errors='strict')
remote_checksum = to_text(self._getContent(remote_url + '.' + checksum_alg, "Failed to retrieve checksum", False), errors='strict')
except UnicodeError as e:
return "Cannot retrieve a valid md5 from %s: %s" % (remote_url, to_native(e))
if(not remote_md5):
return "Cannot find md5 from " + remote_url
return "Cannot retrieve a valid %s checksum from %s: %s" % (checksum_alg, remote_url, to_native(e))
if not remote_checksum:
return "Cannot find %s checksum from %s" % (checksum_alg, remote_url)
try:
# Check if remote md5 only contains md5 or md5 + filename
_remote_md5 = remote_md5.split(None)[0]
remote_md5 = _remote_md5
# remote_md5 is empty so we continue and keep original md5 string
# This should not happen since we check for remote_md5 before
# Check if remote checksum only contains md5/sha1 or md5/sha1 + filename
_remote_checksum = remote_checksum.split(None)[0]
remote_checksum = _remote_checksum
# remote_checksum is empty so we continue and keep original checksum string
# This should not happen since we check for remote_checksum before
except IndexError:
pass
if local_md5.lower() == remote_md5.lower():
if local_checksum.lower() == remote_checksum.lower():
return None
else:
return "Checksum does not match: we computed " + local_md5 + " but the repository states " + remote_md5
return "Checksum does not match: we computed " + local_checksum + " but the repository states " + remote_checksum
return "Path does not exist: " + file
def _local_md5(self, file):
md5 = hashlib.md5()
def _local_checksum(self, checksum_alg, file):
if checksum_alg.lower() == 'md5':
hash = hashlib.md5()
elif checksum_alg.lower() == 'sha1':
hash = hashlib.sha1()
else:
raise ValueError("Unknown checksum_alg %s" % checksum_alg)
with io.open(file, 'rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
md5.update(chunk)
return md5.hexdigest()
hash.update(chunk)
return hash.hexdigest()
def main():
@ -599,6 +613,7 @@ def main():
client_key=dict(type="path", required=False),
keep_name=dict(required=False, default=False, type='bool'),
verify_checksum=dict(required=False, default='download', choices=['never', 'download', 'change', 'always']),
checksum_alg=dict(required=False, default='md5', choices=['md5', 'sha1']),
directory_mode=dict(type='str'),
),
add_file_common_args=True,
@ -639,6 +654,7 @@ def main():
verify_checksum = module.params["verify_checksum"]
verify_download = verify_checksum in ['download', 'always']
verify_change = verify_checksum in ['change', 'always']
checksum_alg = module.params["checksum_alg"]
downloader = MavenDownloader(module, repository_url, local, headers)
@ -683,12 +699,12 @@ def main():
b_dest = to_bytes(dest, errors='surrogate_or_strict')
if os.path.lexists(b_dest) and ((not verify_change) or not downloader.is_invalid_md5(dest, downloader.find_uri_for_artifact(artifact))):
if os.path.lexists(b_dest) and ((not verify_change) or not downloader.is_invalid_checksum(dest, downloader.find_uri_for_artifact(artifact), checksum_alg)):
prev_state = "present"
if prev_state == "absent":
try:
download_error = downloader.download(module.tmpdir, artifact, verify_download, b_dest)
download_error = downloader.download(module.tmpdir, artifact, verify_download, b_dest, checksum_alg)
if download_error is None:
changed = True
else: