Skip to content

Instantly share code, notes, and snippets.

@craig-m-unsw
Last active November 10, 2023 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save craig-m-unsw/6e61f06f6823b9c5319cc9d2ffba4f65 to your computer and use it in GitHub Desktop.
Save craig-m-unsw/6e61f06f6823b9c5319cc9d2ffba4f65 to your computer and use it in GitHub Desktop.
ms_repo_ubuntu.py - script to install MS apt repo with debsig on Ubuntu 20.04 and 22.04

ms apt repo

On Ubuntu 20.04 or 22.04 run ms_repo_ubuntu.py to setup MS software repo as per this, will install PowerShell.

sudo python3 ms_repo_ubuntu.py

Optionally, set some packages as arguments.

sudo python3 ms_repo_ubuntu.py intune-portal mdatp procdump

testing

Testing ms_repo_ubuntu.py on each LTS version of Ubuntu in containers.

This will run testing.ps1 in each container:

./run.sh 20.04
./run.sh 22.04
# Ubuntu Dockerfile for testing
ARG ubuntu_version
FROM ubuntu:${ubuntu_version}
ENV DEBIAN_FRONTEND noninteractive
ENV debug_repo_script True
RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
apt-get update && \
apt-get -y upgrade && \
apt-get install -y software-properties-common apt-transport-https wget python3
ADD ./ms_repo_ubuntu.py /tmp/ms_repo_ubuntu.py
RUN python3 /tmp/ms_repo_ubuntu.py
ENV HOME /root
WORKDIR /root
CMD ["pwsh"]
#!/usr/bin/env python3
import os
import platform
import subprocess
import argparse
# MS PGP Key ID
pgp_key_id = "EB3E94ADBE1229CF"
def debug_print(message):
if debug_repo_script:
print(message)
if 'debug_repo_script' in os.environ:
debug_repo_script = os.environ['debug_repo_script'].lower() == 'true'
else:
debug_repo_script = False
debug_print("debug is on")
def is_debsig_verify_installed():
return os.path.exists("/usr/bin/debsig-verify")
def is_ms_keyfile():
return os.path.exists(f"/usr/share/debsig/keyrings/{pgp_key_id}/microsoft.gpg")
def is_ms_repo_setup():
return os.path.exists("/etc/apt/sources.list.d/microsoft.list")
def is_pwsh_installed():
return os.path.exists("/usr/bin/pwsh")
def install_checks():
if not os.geteuid() == 0:
print("You need to run this script with root privileges.")
exit(1)
tmp_path = '/tmp'
stat_info = os.stat(tmp_path)
# Check if the directory is owned by root
if stat_info.st_uid != 0:
print(f"Warning: /tmp directory is not owned by root (owner UID: {stat_info.st_uid})")
exit(1)
def get_ubuntu_version():
try:
with open("/etc/os-release", "r") as file:
for line in file:
if line.startswith("VERSION_ID="):
return line.split("=")[1].strip().strip('"')
except FileNotFoundError:
print("ERROR: File '/etc/os-release' not found.")
sys.exit(1)
def install_debsig_verify():
if not is_debsig_verify_installed():
debug_print("Installing debsig-verify")
command = f"apt-get install -y debsig-verify"
result = subprocess.run(command, shell=True)
if result.returncode != 0:
print("ERROR: Failed to install debsig-verify.")
exit(1)
def create_directories():
dirs = [
f'/etc/debsig/policies/{pgp_key_id}/',
f'/usr/share/debsig/keyrings/{pgp_key_id}/'
]
for directory in dirs:
os.makedirs(directory, exist_ok=True)
debug_print("made dirs")
def write_microsoft_pol():
pol_data = f"""<?xml version="1.0"?>
<!DOCTYPE Policy SYSTEM "https://www.debian.org/debsig/1.0/policy.dtd">
<Policy xmlns="https://www.debian.org/debsig/1.0/">
<Origin Name="Microsoft" id="{pgp_key_id}" Description="gpgsecurity@microsoft.com"/>
<Selection>
<Required Type="origin" File="microsoft.gpg" id="{pgp_key_id}"/>
</Selection>
<Verification MinOptional="0">
<Required Type="origin" File="microsoft.gpg" id="{pgp_key_id}"/>
</Verification>
</Policy>
"""
with open(f'/etc/debsig/policies/{pgp_key_id}/microsoft.pol', 'w') as f:
f.write(pol_data)
def write_microsoft_key():
if not is_ms_keyfile():
debug_print("Installing Microsoft GPG key")
key_data = f"""-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.7 (GNU/Linux)
mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT
LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV
7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag
OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j
H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr
M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs
ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC
AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH
/32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe
MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy
7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV
KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ
XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+
NdCFTW7wY0Fb1fWJ+/KTsC4=
=J6gs
-----END PGP PUBLIC KEY BLOCK-----
"""
with open('/tmp/microsoft.asc', 'w') as f:
f.write(key_data)
command = f"gpg -o /usr/share/debsig/keyrings/{pgp_key_id}/microsoft.gpg --dearmor /tmp/microsoft.asc"
result = subprocess.run(command, shell=True)
if result.returncode != 0:
print("Failed to install MS GPG key.")
exit(1)
def download_and_verify_package():
ubuntu_version = get_ubuntu_version()
package_url = f"https://packages.microsoft.com/config/ubuntu/{ubuntu_version}/packages-microsoft-prod.deb"
package_path = "/tmp/packages-microsoft-prod.deb"
debug_print(f"Downloading package from {package_url}")
wget_command = f"wget {package_url} -O {package_path}"
result = subprocess.run(wget_command, shell=True)
if result.returncode != 0:
print("Failed to download the Microsoft package.")
exit(1)
debsig_verify_command = f"debsig-verify {package_path}"
debug_print("Verifying package with debsig-verify")
result = subprocess.run(debsig_verify_command, shell=True)
if result.returncode != 0:
print("Failed to verify the package with debsig-verify.")
exit(1)
def install_ms_repo():
debug_print("Installing Microsoft repo")
command = f"apt-get install -y /tmp/packages-microsoft-prod.deb"
result = subprocess.run(command, shell=True)
command2 = f"apt-get update"
debug_print("Updating package cache")
result2 = subprocess.run(command2, shell=True)
if result.returncode != 0:
print("Failed to install MS repo.")
exit(1)
if result2.returncode != 0:
print("Failed to update MS repo details.")
exit(1)
def install_powershell():
debug_print("Installing PowerShell")
command = f"apt-get install -y powershell"
result = subprocess.run(command, shell=True)
if result.returncode != 0:
print("Failed to install Powershell")
exit(1)
def install_additional_packages(packages):
if packages:
debug_print(f"Installing additional packages: {', '.join(packages)}")
for package in packages:
command = f"apt-get install -y {package}"
result = subprocess.run(command, shell=True)
if result.returncode != 0:
print(f"Failed to install package: {package}")
exit(1)
def main():
install_checks()
create_directories()
install_debsig_verify()
write_microsoft_key()
write_microsoft_pol()
if not is_ms_repo_setup():
download_and_verify_package()
install_ms_repo()
if not is_pwsh_installed():
install_powershell()
# Add any packages specified in arguments
if args.packages:
install_additional_packages(args.packages)
if __name__ == "__main__":
# Create an argument parser
parser = argparse.ArgumentParser(description='Install Microsoft software and optionally additional packages.')
# Add an argument for specifying additional packages
parser.add_argument('packages', nargs='*', help='Additional packages to install')
args = parser.parse_args()
# main
main()
#!/usr/bin/env bash
# enable DCT for Ubuntu image
export DOCKER_CONTENT_TRUST=1
# Ensure the script is executed with an argument.
if [ $# -eq 0 ]; then
echo "Usage: $0 <ubuntu_version>"
exit 1
fi
# Extract the Ubuntu version from the command line argument.
ubuntu_version="$1"
# Build the Docker image, passing the "ubuntu_version" build ARG.
docker build \
--build-arg ubuntu_version="${ubuntu_version}" \
-t ubuntu_ms_ps:"${ubuntu_version}" .
export DOCKER_CONTENT_TRUST=0
docker run \
--mount type=bind,source="$(pwd)/testing.ps1",target=/tmp/testing.ps1 \
ubuntu_ms_ps:"${ubuntu_version}" \
pwsh /tmp/testing.ps1
echo "finished on ${ubuntu_version}."
$osName = [System.Runtime.InteropServices.RuntimeInformation]::OSDescription
$hostname = [System.Net.Dns]::GetHostName()
$ipAddresses = [System.Net.Dns]::GetHostAddresses($hostname) | ForEach-Object { $_.ToString() }
$currentTime = Get-Date
Write-Host "---------- testing.ps1 ----------"
Write-Host "Operating System: $osName"
Write-Host "Hostname: $hostname"
Write-Host "IP Addresses: $($ipAddresses -join ', ')"
Write-Host "Current Time: $currentTime"
Write-Host "---------------------------------"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment