Last active
November 28, 2023 22:39
-
-
Save craig-m-unsw/4f0c9a30362517dd087aa54869726ab2 to your computer and use it in GitHub Desktop.
get_rclone.py - find latest Rclone release and download + check all packages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # find latest Rclone release and download + check all packages as per https://rclone.org/release_signing/ | |
| # | |
| # example use: | |
| # | |
| # $ python3 -m venv get_rclone | |
| # $ source get_rclone/bin/activate | |
| # $ pip install python-gnupg requests | |
| # $ ./get_rclone.py | |
| import re | |
| import hashlib | |
| import os | |
| import requests | |
| import gnupg | |
| #---------------------------------------------------------------------------------------------------------------------------- | |
| # ask GitHub API for the latest release of rclone/rclone | |
| url = "https://api.github.com/repos/rclone/rclone/releases/latest" | |
| response = requests.get(url) | |
| if response.status_code == 200: | |
| release_info = response.json() | |
| tag_name = release_info["tag_name"] | |
| print("Latest rclone release tag: " + tag_name) | |
| else: | |
| print("Failed to retrieve release information. Status code: " + str(response.status_code)) | |
| exit(1) | |
| version = tag_name | |
| #version = "v1.64.2" | |
| base_url = "https://github.com/rclone/rclone/releases/download/" | |
| base_url_full = base_url + version | |
| sha256_url = base_url_full + "/" + "SHA256SUMS" | |
| # Save SHA256SUMS file as | |
| sha256_file_name = f"SHA256SUMS_{version}" | |
| # Regular expression pattern to match files in SHA256SUMS to download | |
| file_name_pattern = r"rclone-v.*\.(zip|deb|rpm|tar\.gz)" | |
| # Define the folder for downloaded files | |
| download_folder = version | |
| # public pgp key to check signature with | |
| pub_key = """ | |
| -----BEGIN PGP PUBLIC KEY BLOCK----- | |
| mQGiBDuy3V0RBADVQOAF5aFiCxD3t2h6iAF2WMiaMlgZ6kX2i/u7addNkzX71VU9 | |
| 7NpI0SnsP5YWt+gEedST6OmFbtLfZWCR4KWn5XnNdjCMNhxaH6WccVqNm4ALPIqT | |
| 59uVjkgf8RISmmoNJ1d+2wMWjQTUfwOEmoIgH6n+2MYNUKuctBrwAACflwCg1I1Q | |
| O/prv/5hczdpQCs+fL87DxsD/Rt7pIXvsIOZyQWbIhSvNpGalJuMkW5Jx92UjsE9 | |
| 1Ipo3Xr6SGRPgW9+NxAZAsiZfCX/19knAyNrN9blwL0rcPDnkhdGwK69kfjF+wq+ | |
| QbogRGodbKhqY4v+cMNkKiemBuTQiWPkpKjifwNsD1fNjNKfDP3pJ64Yz7a4fuzV | |
| X1YwBACpKVuEen34lmcX6ziY4jq8rKibKBs4JjQCRO24kYoHDULVe+RS9krQWY5b | |
| e0foDhru4dsKccefK099G+WEzKVCKxupstWkTT/iJwajR8mIqd4AhD0wO9W3MCfV | |
| Ov8ykMDZ7qBWk1DHc87Ep3W1o8t8wq74ifV+HjhhWg8QAylXg7QlTmljayBDcmFp | |
| Zy1Xb29kIDxuaWNrQGNyYWlnLXdvb2QuY29tPohXBBMRAgAXBQI7st1dBQsHCgME | |
| AxUDAgMWAgECF4AACgkQk5NeAv87VPoPswCfaetrHxFhv6vpjadYWc6tyAZJHD4A | |
| n2IfppvFB0vdOFgYBz/+u/6rN4p1iHEEExEIADEFCwcKAwQDFQMCAxYCAQIXgBYh | |
| BPv3N+zp+KsYYEvSrJOTXgL/O1T6BQJeODZSAhkBAAoJEJOTXgL/O1T6WaYAniMf | |
| kXJQvNK2OKy5O8ctNXPobjh5AJ9pHlAZkU+x56cTmJzZZ5BwFya2gYhXBBMRAgAX | |
| BQI7st1dBQsHCgMEAxUDAgMWAgECF4AACgkQk5NeAv87VPoPswCgwDDvPZfRHenT | |
| ca1r22pCum0FSlkAniLGFmVYPIcnMMF9OxQ6wBy34oZGiQIzBBABCgAdFiEEje07 | |
| Kgm0YIzmpewHpU4nXkJI4BYFAl3Ap2EACgkQpU4nXkJI4BYFjw//Y3MtrkqtACWp | |
| idlcLHRYpU+e17dhsZBP2afq56/B2zXFvtYnH0QyGN/YDjHMfK6Zi2Xxem7jg8ww | |
| qH9s7eBAJUwbM6oAuhvQfdqpLCygAAep1ZKhuguSEUvJjoajqPQNjJE/aqini4Es | |
| fnEVuK+y9L+smQvtFFx9U+PV7l6Z9WE3SFYtFvjUBL3FeaIfh36fUyj4xXR17Guj | |
| ADtTHiWR4xElJ16NCj2VhfbE2wxoG2/SHDfHpzjW3B/pRJZOCOvJZcrtZRNqruff | |
| 8JGvLObswTlNiTn9rjc5lCPkMhnEke5i20BIymlPMlaNCE64AkkB/FDFed69b7u8 | |
| R1E1LivBL0qoXIt1s8E+UW9ADBCxwloFeHroZhDPs6Y00EK+hGSJonB1pzguVc0u | |
| MA9v9Gfcx099KQbfuSZefBCzpkktsmulb/59WEfK1Q4oVjdmCUG3/qwmLzAilzs6 | |
| YaD75V6lp1lCON2jWod5xYSPsuvo2T0Exj4Q5MZcLVwqzH4UnmJPqdRVxWhhJEDE | |
| qlsU+t0LCpDt4saVI5A91k5HMqFOJpX2hbLEx5OG3/gksED6FcZd1mwUVWEChjC0 | |
| L6UNqpQZi+bNAX0CxY9XeqEIMN/EhLDbmLEwUHgMC3G4hX813k23mSWHBRsa0Mik | |
| PCXX3tRioqPNF5ALl4gOmnF6ZD+WAQeJAjMEEAEIAB0WIQTjs1jchY+zB/SBcLnL | |
| Db68XzLIHQUCZPRnNAAKCRDLDb68XzLIHZSAD/oCk9Z0xJfbpriphTBxFy7bWyPK | |
| F1lM1GZZaLKkktGfunf1i0Q7rhwpNu+u1launlOTp6ZoY36Ce2Qa1eSxWAQdjVaj | |
| w9kOHXCAewrTREOMY/mb7RVGjajo0Egl8T9iD3JRyaxu2iVtbpZYuqehtGG28CaC | |
| zmtqE+EJcx1cGqAGSuuaDWRYlVX8KDip44GQB5Lut30vwSIoZG1CPCR6VE82u4cl | |
| 3mYZUfcJkCHsiLzoeadVzb+fOd+2ybzBn8Y77ifGgM+dSFSHe03mFfcHPdp0QImF | |
| 9HQR7XI0UMZmEJsw7c2vDrRa+kRY2A4/amGn4Tahuazq8g2yqgGm3yAj49qGNarA | |
| au849lDr7R49j73ESnNVBGJ9ShzU4Ls+S1A5gohZVu2s1fkE3mbAmoTfU4JCrpRy | |
| dOuL9xRJk5gbL44sKeuGODNshyTPJzG9DmRHpLsBn59v8mg5tqSfBIGqcqBxxnYH | |
| JnkK801MkaLW2m7wDmtz6P3TW86gGukzfIN3/OufLjnpN3Nx376JwWDDIyif7sn6 | |
| /q+ZMwGz9uLKZkAeM5c3Dh4ygpgliSLoV2bZzDz0iLxKWW7QOVVdWHmlEqbTldpQ | |
| 7gUEPG7mxpzVo0xd6nHncSq0M91x29It4B3fATx/iJB2eardMzSsbzHiwTg0eswh | |
| YYGpSKZLgp4RShnVAbkCDQQ7st2BEAgAjpB0UGDf/FrWAUo9jLWKFX15J0arBZkY | |
| m+iRax8K8fLnXzS2P+9Q04sAmt2qCUxK9681Nd7xtPrkPrjbcACwuFyH3Cr9o2qs | |
| eiVNgAHPFGKCNxLX/9PKWfmdoZTOVVBcNV+sOTcx382uR04WPuv9jIwXT6JbCkXP | |
| aoCMv3mLnB9VnWRYatPYCaK8TXAPWxZP8lrcUMjQ1GRTQ1vP9rRMp7iaXyItW1le | |
| lNFvHEII92QddeBLK7V5ng2sX/BMm6/AafXZMnUQX3lpWQfEBTDT4qYsZ1zIEb4g | |
| q4dqauyNYgBcZdX//8oDE+BS2FxxDTccyOW0Wyt2Z6flDTfhgzd46wADBQf+MAqI | |
| gADwulmZk+e30Znj46VmnbZUB/J8M4WXg6X5xaOQsCCMAWybmCc4pxFIT/1c/GdC | |
| qSHDv5nKBi5QyBMMn33/kgzVRAveihL6gWsNoT31Lxst457XuyRx1dwD8rzdWoP2 | |
| b3etBGdu0P7vnOoqRmf1Y0XIoJeDk/o8U901hG2VAo5zAVH2YdEtSZqlBIAzxjak | |
| KAAtnsZWIpBxrz9NPVOBmT18kxlgZ7P4iU4/FMnGOfzT6/LCTj/B0hZKJCP7y7lH | |
| NP2yOabvvBsxU0ZGph1b8R6Zb1nP2+LQIi8kaBs8ypy7HDx7/mWe5DoyLe4NHQ/Z | |
| E0gCEWt1mlVIwTzFBohGBBgRAgAGBQI7st2BAAoJEJOTXgL/O1T6YsEAoLZx0XLt | |
| 4tpAC/LNwTZUrodUiOckAKC4DTRvEtC4nj5EImssVk/xmU3ax5kCDQRjJI69ARAA | |
| wCCaKZZmZe8mmusRuoHrqeVImFo+JUTNiktszB/l97INgZCSpVGFOcc4l4Weoioy | |
| hObJV5wnpFjhadhpiRG1XYzNYi6vNKz8lsUkFxfkIFiXU2kRkwtQShiWf4LmobDQ | |
| sY9SXRK2cVEFQwOqK9E0k99ZKoaQ31aqq1zcAzkRlBrJmjgmRJHX3DltA7z676Ap | |
| YEJgAkDRBXFe3zViuxZ0/MMYqtwsbePvOMkXlPmQJ8havOjZRa0mEZtDekMt11vv | |
| 1bG1qFebMFuwYVd7YZ1kzL8NU8gNOtuW0E67Ts5voZdlZiQAbDke9V9uj9+hfae6 | |
| vICrZ7eriPGVD6BetGNjUNFN+8fwHMycOvvHjZ/JlN8lCfw4ImK4F18ms51pqD74 | |
| 3w0b2VvoQOkkCzEyUReTixh60aMIabx8so4BmFdi7cK9E+4/WU933d+dSEVgr9Hp | |
| ast2WoNTo7cPWgIcxSctWvq9AIULLDVytI2BVRbIRL5vZHNIlE839AVbef8SP5Vc | |
| V+8xjNRw3bzpxhnu4TqYTrvexvq7YOsMxVc9qqN2w8w+Q6jL/0Hjq2fUouV6JH/u | |
| 6GY1vo9dCOXMROS/fD3qJfDIb/NZuYqnt2jQArJW2YVxL+4DE7yKvSNaHGY5kwEV | |
| BrQCCTb16ANWxUHkBBuSP2+hYKrVQPAisdsovHRgcF0AEQEAAbQlTmljayBDcmFp | |
| Zy1Xb29kIDxuaWNrQGNyYWlnLXdvb2QuY29tPokCTgQTAQgAOBYhBOOzWNyFj7MH | |
| 9IFwucsNvrxfMsgdBQJjJI69AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJ | |
| EMsNvrxfMsgdxW8QAIckFmxogPfLD6kqIoiZerqPRcz5rYBfxa7lgQkuoLaqWhCP | |
| QR+e5Ug3bqxexkYQrTyZwqzTTgntTTWt4hSg75mgAujMQh1bsYbxcSHiLSh3Q8bO | |
| AaX3o+ewycqKRvaVLYD7m/f8ZHgjRdwtEV3M9tVIOpa/KB51+3PM23Kx7pWP8RnT | |
| mLhbxDCQTYE4yiLFPBIoG8NH1raLXonvLHP+wFs2OJ18fkq3DHTKK48dTRs/QyNl | |
| /kgmuFUv/SyXDEoe9XdweNnN4N005R7bHW9iJEoV8KBFJi9/K89jokwrrRCUk1Pz | |
| p/QXSKYLX59uqufL4LQOCtEhmVJPTQKCd4eUhvCva70efRm1fwqV/PHJDXB2Y84Q | |
| oBPyxitFJGvBc1RsB3t1iO9IAuWnfFLYBayVGbpHseO5RdgJT/Q1hWeZTFi3vfXX | |
| snuDSl5FcjLhDVe5rrAa/oAGki2fA7YOeK7PB0uwK7O8s2ZErDHnV99zYMVy7hnY | |
| LhxDhic4mQ/1uJ/6mcEO+6NU4FM6EA0Bt28WTgRyOM2WnZ8xjBBmHtV4ucvmbQn1 | |
| CCZUCe6HG06l8/soaMKiCZFS0CKwed9ymhlHPp5nyD3CJw53EKdEDQAjSOxc9sI0 | |
| L5/P73ijRkOVz5xMtyxXXAnsyVa0yXo/rbzBGjKMcJeuAa1168a3ydu0gMMWiF0E | |
| EBEIAB0WIQT79zfs6firGGBL0qyTk14C/ztU+gUCZPRnIgAKCRCTk14C/ztU+nDL | |
| AJ99G+k/+uCkMnJuQazlb10HeiF4DwCgx+BNLTMkLduN9F+bqPsKq0oVsCa5Ag0E | |
| YySOvQEQALoUUvMMNBKr7xMUVSe/lvBQUhzdthcDARdCf5m/UQoBYdyfYEA7m0x1 | |
| 5fKMl2duZdT9pYTSt60LeRXiC4bJaMCl60Nb2gwPF7ko32TFLpEyRHznVeEw+ExV | |
| OU82lOWwI6AOFwHO4hL+wgK5RXV9qgve3n30ccTvKRHpjmQSa2YD3S5pO20KRsJt | |
| iU8nm1+e7zXGEqWvR3L4QhJtN4Xtda+Gv95lH22Y+XnHri9MNMYbXrhTrOAig1ne | |
| 5GF3goG/yps6QyoV2zdY+Zqojpi9sCtRdiwbETbp8izQNV53QBqORIILBuzZpmqJ | |
| gSNbbFsAdJkmPfLbjx57BieF2YUvsl0DtVc8KdN6UCrhQF2CNaGdWWpJyKF6AHkE | |
| iIt0npvlgAM8ZZ0y0WF5XqefvIEMx7DmpKZ822gvR2aTmDJzPhgFTVhelVHDJ6NS | |
| l5FUhA+DB1U7SwFULc2VFJdDa2zrnM0T+bz5cc8mi1zazzcBklzLNpRoT0Iex2LC | |
| +KPFmsBbObKGffvDwQkEJgBJ9FweRGLfiHOo1V4E+QwIZhoch/H5u9+2J3Hp0S/r | |
| H6Jn97AjYZMUVZBC4rICBaIevqaIuP/Qno2hRSkccF388lLBWRW/qa8vaRpk9Xgt | |
| 8umvLmnumEKmmWxF6rHZu34ijgnaWfuunydfiu/v0kd6H5tO8h9NABEBAAGJAjYE | |
| GAEIACAWIQTjs1jchY+zB/SBcLnLDb68XzLIHQUCYySOvQIbDAAKCRDLDb68XzLI | |
| HcZpD/oCT20Tufzh3YvRqd7+nAziHzPoz15bkd0Y2B9wAQ4kkT4o6/vSSqpQeBAL | |
| UVh54cTaMkyFUTr53U5rK0QyEFrwa1j6wQvHSbOhaCAVacii9n8eyELI0755eCAN | |
| 7w7mRsS05hTgKdQwn4TKnb9FvST+TMyyBcL8IPnHcmYbiX1repRlUZ5VvyWtQDO2 | |
| Z3BISWtOnMJjItQ9N8zj3KkeLVtWennroYpDEJo2qpb5Ga320Mijoh0Mm8r3uM7o | |
| rarpfnEsUGiko++elHVbgv7iTxyfxV+ny14ROAcY6VtF8a6MUflKYnAJytD9fwGt | |
| 2+Of7CB72b3Zq47XLh7FXozqWL2zCVrU5u55NXKGaSRXmPec54RrtAF0BfGpkbHZ | |
| W4xOS2E4IzBNf3rhh7Nj+4MCGmx7RuRzHvlkltS38ktXQmUfch8pFhLKW8byxFhu | |
| Je3QS3vnKmA2dQzHKZDQj8uyHUUD0WQlBtaY2p7G4zFhuC+xNHDs8Xbo+NCgsmg7 | |
| 8qSub42rXViT0kK9xeAKr3qKbumQqIfXHWQvamFHJeIpvrLEffhWKZc83PXpL9wY | |
| JP/Rm0jTtKJeqD8w7rnafOi9qKyE2FgpltdWzsUSPDjqMlCgCrggqtUzTgKYl1S/ | |
| 6jXcPGkEadKE/t3kelkupnlwlyVLxF7NaIrb8fAqCau0MWIh4g== | |
| =Iv9u | |
| -----END PGP PUBLIC KEY BLOCK----- | |
| """ | |
| #---------------------------------------------------------------------------------------------------------------------------- | |
| # download dir | |
| if not os.path.exists(download_folder): | |
| os.makedirs(download_folder) | |
| # Read the content of the SHA256SUMS file | |
| if not os.path.exists(sha256_file_name): | |
| # Download the SHA256SUMS file if it doesn't exist | |
| response = requests.get(sha256_url) | |
| if response.status_code == 200: | |
| sha256_content = response.text | |
| with open(sha256_file_name, 'w') as file: | |
| file.write(sha256_content) | |
| else: | |
| print(f"Failed to download SHA256SUMS file.") | |
| exit(1) | |
| # Check PGP signature in SHA256SUMS | |
| gpg_ctx = gnupg.GPG() | |
| import_result = gpg_ctx.import_keys(pub_key) | |
| # Read the content of the signed message from the file | |
| with open(sha256_file_name, "r") as file: | |
| signed_message = file.read() | |
| # Verify the signature | |
| verification = gpg_ctx.verify(signed_message) | |
| # notice | |
| if verification.valid: | |
| print("PGP Signature of 'SHA256SUMS' is valid.") | |
| else: | |
| print("PGP Signature of 'SHA256SUMS' NOT valid.") | |
| exit(1) | |
| # Regex pattern to match lines with the desired file name and SHA256 sums | |
| regex_pattern = f"([0-9a-f]{{64}}) ({file_name_pattern})" | |
| # Read the content of the SHA256SUMS file | |
| with open(sha256_file_name, 'r') as file: | |
| sha256_content = file.read() | |
| # Search for matches in the content | |
| matches = re.findall(regex_pattern, sha256_content) | |
| # Check if the file name is found in SHA256SUMS | |
| if not matches: | |
| print(f"No matching files found in SHA256SUMS for pattern '{file_name_pattern}'.") | |
| else: | |
| for match in matches: | |
| sha256_expected = match[0] # Get the expected SHA256 sum from the matches | |
| file_name_to_check = match[1] # Get the file name from the matches | |
| # Calculate the full path to the downloaded file | |
| file_path = os.path.join(download_folder, file_name_to_check) | |
| # Check if the file exists | |
| if not os.path.exists(file_path): | |
| # Download the file if it doesn't exist | |
| download_url = f"{base_url_full}/{file_name_to_check}" | |
| response = requests.get(download_url) | |
| if response.status_code == 200: | |
| # Create the folder if it doesn't exist | |
| os.makedirs(os.path.dirname(file_path), exist_ok=True) | |
| with open(file_path, 'wb') as file: | |
| file.write(response.content) | |
| print(f"Downloaded file '{file_name_to_check}' to '{download_folder}' from {download_url}") | |
| else: | |
| print(f"Failed to download file '{file_name_to_check}' from {download_url}.") | |
| continue # Skip checking SHA256 sum | |
| # Calculate the SHA256 sum of the actual file | |
| with open(file_path, 'rb') as file_to_check: | |
| file_content = file_to_check.read() | |
| sha256_actual = hashlib.sha256(file_content).hexdigest() | |
| # Compare the calculated SHA256 sum with the expected sum | |
| if sha256_actual == sha256_expected: | |
| print(f"File '{file_name_to_check}' SHA256 sum matches the expected value.") | |
| else: | |
| print(f"File '{file_name_to_check}' SHA256 sum does not match the expected value.") | |
| exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment