Skip to content

Commit bb9e339

Browse files
Merge branch 'main' into azure_linux_did
2 parents 03a8101 + 10b6e71 commit bb9e339

File tree

6 files changed

+210
-15
lines changed

6 files changed

+210
-15
lines changed

src/azure-cli/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "azure-cli",
3-
"version": "1.2.8",
3+
"version": "1.2.9",
44
"name": "Azure CLI",
55
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/azure-cli",
66
"description": "Installs the Azure CLI along with needed dependencies. Useful for base Dockerfiles that often are missing required install dependencies like gpg.",

src/azure-cli/install.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,15 @@ install_using_apt() {
9898
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
9999
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
100100
echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/azure-cli/ ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/azure-cli.list
101-
apt-get update
101+
102+
# This is a workaround for the fact that Azure CLI is not yet a supported package for debian trixie. Once Azure CLI is supported we should revert to avoid script failure for non Azure CLI packages
103+
if ! (apt-get update); then
104+
echo "(!) Failed to update apt cache, removing repository file"
105+
rm -f /etc/apt/sources.list.d/azure-cli.list
106+
else
107+
echo "WARNING: apt-get update succeeded. The workaround for broken Azure CLI install on Debian Trixie may no longer be needed."
108+
echo "TODO: Consider reverting to a simple `apt-get update` if the Azure CLI repo works reliably for debian trixie"
109+
fi
102110

103111
if [ "${AZ_VERSION}" = "latest" ] || [ "${AZ_VERSION}" = "lts" ] || [ "${AZ_VERSION}" = "stable" ]; then
104112
# Empty, meaning grab the "latest" in the apt repo
@@ -135,7 +143,7 @@ install_using_pip_strategy() {
135143

136144
install_with_pipx() {
137145
echo "(*) Attempting to install globally with pipx..."
138-
local ver="$1"
146+
local ver="$1"
139147
export
140148
local
141149

src/python/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "python",
3-
"version": "1.7.1",
3+
"version": "1.8.0",
44
"name": "Python",
55
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/python",
66
"description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.",

src/python/install.sh

Lines changed: 167 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ if [ "${ADJUSTED_ID}" = "rhel" ] && [ "${VERSION_CODENAME-}" = "centos7" ]; then
6969
fi
7070

7171
# To find some devel packages, some rhel need to enable specific extra repos, but not on RedHat ubi images...
72-
INSTALL_CMD_ADDL_REPO=""
72+
INSTALL_CMD_ADDL_REPOS=""
7373
if [ ${ADJUSTED_ID} = "rhel" ] && [ ${ID} != "rhel" ]; then
7474
if [ ${MAJOR_VERSION_ID} = "8" ]; then
7575
INSTALL_CMD_ADDL_REPOS="--enablerepo powertools"
@@ -93,6 +93,27 @@ else
9393
INSTALL_CMD="${PKG_MGR_CMD} ${INSTALL_CMD_ADDL_REPOS} -y install --noplugins --setopt=install_weak_deps=0"
9494
fi
9595

96+
# Install Time::Piece Perl module required by OpenSSL 3.0.18+ build system on CentOS 7/RHEL 7
97+
install_time_piece() {
98+
echo "(*) Ensuring Time::Piece Perl module is available for OpenSSL 3.0.18+ build..."
99+
100+
# Check if Time::Piece is already available (it's usually in Perl core)
101+
if perl -MTime::Piece -e 'exit 0' 2>/dev/null; then
102+
echo "(*) Time::Piece already available"
103+
return 0
104+
fi
105+
106+
echo "(*) Time::Piece not found, installing perl-Time-Piece package..."
107+
108+
# Install perl-Time-Piece package for CentOS 7/RHEL 7
109+
if ${INSTALL_CMD} perl-Time-Piece; then
110+
echo "(*) perl-Time-Piece installed for OpenSSL 3.0.18+ build"
111+
else
112+
echo "(!) Failed to install perl-Time-Piece package. This will cause OpenSSL 3.0.18+ build to fail"
113+
return 1
114+
fi
115+
}
116+
96117
# Clean up
97118
clean_up() {
98119
case ${ADJUSTED_ID} in
@@ -478,6 +499,130 @@ install_cpython() {
478499
curl -sSL -o "/tmp/python-src/${cpython_tgz_filename}" "${cpython_tgz_url}"
479500
fi
480501
}
502+
# Get system architecture for downloads
503+
get_architecture() {
504+
local architecture=""
505+
case $(uname -m) in
506+
x86_64) architecture="amd64" ;;
507+
aarch64 | armv8*) architecture="arm64" ;;
508+
aarch32 | armv7* | armvhf*) architecture="armhf" ;;
509+
i?86) architecture="386" ;;
510+
*) echo "(!) Architecture $(uname -m) unsupported"; exit 1 ;;
511+
esac
512+
echo ${architecture}
513+
}
514+
515+
# Install cosign with multi-distro support
516+
install_cosign() {
517+
518+
COSIGN_VERSION="latest"
519+
local cosign_url='https://github.com/sigstore/cosign'
520+
local architecture=$(get_architecture)
521+
522+
find_version_from_git_tags COSIGN_VERSION "${cosign_url}"
523+
524+
# Remove 'v' prefix if present for download URL
525+
local version_for_url="${COSIGN_VERSION#v}"
526+
527+
local cosign_filename="/tmp/cosign_${version_for_url}_${architecture}.deb"
528+
local cosign_url="https://github.com/sigstore/cosign/releases/download/v${version_for_url}/cosign_${version_for_url}_${architecture}.deb"
529+
530+
echo "Downloading cosign from: ${cosign_url}"
531+
532+
if curl -L -f --fail-with-body "${cosign_url}" -o "$cosign_filename" 2>/dev/null; then
533+
echo "(*) Successfully downloaded cosign v${COSIGN_VERSION}"
534+
else
535+
echo -e "\n(!) Failed to fetch cosign v${COSIGN_VERSION}..."
536+
# Try previous version
537+
find_prev_version_from_git_tags COSIGN_VERSION "https://github.com/sigstore/cosign"
538+
echo -e "\nAttempting to install previous cosign ${COSIGN_VERSION} version as fallback mechanism"
539+
540+
version_for_url="${COSIGN_VERSION#v}"
541+
cosign_filename="/tmp/cosign_${version_for_url}_${architecture}.deb"
542+
cosign_url="https://github.com/sigstore/cosign/releases/download/v${version_for_url}/cosign_${version_for_url}_${architecture}.deb"
543+
544+
if ! curl -L -f --fail-with-body "${cosign_url}" -o "$cosign_filename" 2>/dev/null; then
545+
echo "(!) Failed to download cosign v${COSIGN_VERSION} as fallback"
546+
return 1
547+
fi
548+
fi
549+
550+
# Install the package
551+
if [ -f "$cosign_filename" ]; then
552+
dpkg -i "$cosign_filename"
553+
rm "$cosign_filename"
554+
echo "Installation of cosign succeeded with ${COSIGN_VERSION}."
555+
else
556+
echo "(!) Failed to install cosign package"
557+
return 1
558+
fi
559+
560+
}
561+
562+
# COSIGN signature verification for python versions >= 3.14
563+
cosign_verification() {
564+
local VERSION="$1"
565+
566+
# Ensure cosign is installed
567+
if ! type cosign > /dev/null 2>&1; then
568+
echo "(*) cosign not found, installing..."
569+
if ! install_cosign; then
570+
echo "(!) Failed to install cosign"
571+
return 1
572+
fi
573+
else
574+
echo "(*) cosign is already available on the system"
575+
fi
576+
577+
echo "(*) Attempting COSIGN verification for Python ${VERSION}..."
578+
579+
# Check if COSIGN signature files exist (these don't exist yet for Python releases)
580+
local cosign_sig_url="${cpython_tgz_url}.sig"
581+
local cosign_cert_url="${cpython_tgz_url}.pem"
582+
583+
# Download COSIGN signature and certificate files with proper error handling
584+
echo "(*) Checking for cosign signature files..."
585+
if ! curl -sSL -f --fail-with-body -o "/tmp/python-src/${cpython_tgz_filename}.sig" "${cosign_sig_url}" 2>/dev/null; then
586+
echo "(!) COSIGN signature file not available for Python ${VERSION}"
587+
echo " Signature URL: ${cosign_sig_url}"
588+
return 1
589+
fi
590+
591+
if ! curl -sSL -f --fail-with-body -o "/tmp/python-src/${cpython_tgz_filename}.pem" "${cosign_cert_url}" 2>/dev/null; then
592+
echo "(!) COSIGN certificate file not available for Python ${VERSION}"
593+
echo " Certificate URL: ${cosign_cert_url}"
594+
return 1
595+
fi
596+
597+
# Perform COSIGN verification
598+
if cosign verify-blob \
599+
--certificate "/tmp/python-src/${cpython_tgz_filename}.pem" \
600+
--signature "/tmp/python-src/${cpython_tgz_filename}.sig" \
601+
--certificate-identity-regexp=".*" \
602+
--certificate-oidc-issuer-regexp=".*" \
603+
"/tmp/python-src/${cpython_tgz_filename}"; then
604+
echo "(*) COSIGN signature verification successful"
605+
return 0
606+
else
607+
echo "(!) COSIGN signature verification failed"
608+
return 1
609+
fi
610+
}
611+
612+
# GPG verification for python versions < 3.14
613+
gpg_verification() {
614+
echo "(*) Using GPG signature verification..."
615+
if [[ ${VERSION_CODENAME} = "centos7" ]] || [[ ${VERSION_CODENAME} = "rhel7" ]]; then
616+
receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
617+
else
618+
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
619+
fi
620+
echo "Downloading ${cpython_tgz_filename}.asc..."
621+
curl -sSL -o "/tmp/python-src/${cpython_tgz_filename}.asc" "${cpython_tgz_url}.asc"
622+
gpg --verify "${cpython_tgz_filename}.asc"
623+
echo "(*) GPG signature verification successful"
624+
}
625+
481626

482627
install_from_source() {
483628
VERSION=$1
@@ -496,6 +641,8 @@ install_from_source() {
496641
case ${VERSION_CODENAME} in
497642
centos7|rhel7)
498643
check_packages perl-IPC-Cmd
644+
# Install Time::Piece Perl module required by OpenSSL 3.0.18+ build system
645+
install_time_piece
499646
install_openssl3
500647
ADDL_CONFIG_ARGS="--with-openssl=${SSL_INSTALL_PATH} --with-openssl-rpath=${SSL_INSTALL_PATH}/lib"
501648
;;
@@ -507,15 +654,27 @@ install_from_source() {
507654
install_prev_vers_cpython "${VERSION}"
508655
fi
509656
fi;
510-
# Verify signature
511-
if [[ ${VERSION_CODENAME} = "centos7" ]] || [[ ${VERSION_CODENAME} = "rhel7" ]]; then
512-
receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
657+
658+
# Discontinuation of PGP signatures for releases of Python 3.14 or future versions
659+
# CPython release artifacts are additionally signed with Sigstore starting with the Python 3.11.0
660+
local major_version=$(echo "$VERSION" | cut -d. -f1)
661+
local minor_version=$(echo "$VERSION" | cut -d. -f2)
662+
echo "(*) Detected Python version: ${major_version}.${minor_version}"
663+
if (( major_version > 3 )) || { (( major_version == 3 )) && (( minor_version >= 14 )); }; then
664+
echo "(*) Python 3.14+ detected. Attempting cosign verification..."
665+
if cosign_verification "$VERSION"; then
666+
echo "(*) COSIGN verification successful."
667+
else
668+
echo "(*) COSIGN verification failed or not available for Python ${VERSION}"
669+
echo "(*) WARNING: Installing Python ${VERSION} without signature verification"
670+
echo "(*) This is expected for newly released versions where cosign signatures are not yet available"
671+
echo "(*) Python 3.14+ discontinued PGP signatures in favor of cosign, but cosign signatures may take time to be published"
672+
fi
513673
else
514-
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
674+
echo "(*) Python < 3.14 detected. Using GPG signature verification..."
675+
gpg_verification
676+
echo "(*) GPG verification successful."
515677
fi
516-
echo "Downloading ${cpython_tgz_filename}.asc..."
517-
curl -sSL -o "/tmp/python-src/${cpython_tgz_filename}.asc" "${cpython_tgz_url}.asc"
518-
gpg --verify "${cpython_tgz_filename}.asc"
519678

520679
# Update min protocol for testing only - https://bugs.python.org/issue41561
521680
if [ -f /etc/pki/tls/openssl.cnf ]; then
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Import test library for `check` command
6+
source dev-container-features-test-lib
7+
8+
check "version" az --version
9+
10+
check "docker installed" bash -c "type docker"
11+
12+
# Report result
13+
reportResults

test/azure-cli/scenarios.json

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"extensions": "aks-preview,amg,containerapp"
99
}
1010
}
11-
},
11+
},
1212
"install_extensions": {
1313
"image": "mcr.microsoft.com/devcontainers/base:jammy",
1414
"user": "vscode",
@@ -39,7 +39,7 @@
3939
}
4040
}
4141
},
42-
"install_bicep_trixie": {
42+
"install_bicep_trixie": {
4343
"image": "mcr.microsoft.com/devcontainers/base:trixie",
4444
"user": "vscode",
4545
"features": {
@@ -68,7 +68,7 @@
6868
"installUsingPython": true
6969
}
7070
}
71-
},
71+
},
7272
"install_with_python_3_12_bookworm": {
7373
"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm",
7474
"user": "vscode",
@@ -87,5 +87,20 @@
8787
"installUsingPython": "true"
8888
}
8989
}
90+
},
91+
"install_azcli_dotnet_dockerindocker_trixie": {
92+
"image": "mcr.microsoft.com/devcontainers/dotnet:dev-10.0-preview-trixie",
93+
"user": "vscode",
94+
"features": {
95+
"azure-cli": {
96+
"version": "latest"
97+
},
98+
"dotnet": {
99+
"aspNetCoreRuntimeVersions": "8.0"
100+
},
101+
"docker-in-docker": {
102+
"moby": false
103+
}
104+
}
90105
}
91106
}

0 commit comments

Comments
 (0)