diff --git a/.github/workflows/orka-templates.yml b/.github/workflows/orka-templates.yml index a4bb25074..242ed7782 100644 --- a/.github/workflows/orka-templates.yml +++ b/.github/workflows/orka-templates.yml @@ -22,7 +22,28 @@ jobs: - name: Set up Packer uses: hashicorp/setup-packer@1aa358be5cf73883762b302a3a03abd66e75b232 #v3.1.0 + - name: Create dummy Packer variables file + working-directory: orka/templates + run: | + cat > variables.auto.pkrvars.hcl <<'EOF' + orka_endpoint = "https://mock-orka-endpoint" + xcode_version = "mock-xcode_version" + macos_version = "mock-macos_version" + orka_source_image = "mock-orka_source_image" + ssh_new_password = "mock-ssh_new_password" + ssh_image_password = "mock-ssh_image_password" + ssh_new_public_key = "mock-new_public_key" + EOF + - name: Mock secret files for validate + working-directory: orka/templates + run: | + mkdir -p files/secrets + : > "files/secrets/Apple Developer ID Node.js Foundation.p12" + : > "files/secrets/id_rsa" + - name: Initialize Packer + env: + ORKA_AUTH_TOKEN: 'mock-orka-auth-token' run: | for file in $(find . -name '*.pkr.hcl'); do echo "Initializing $file" @@ -32,25 +53,10 @@ jobs: - name: Validate Packer templates env: - ORKA_ENDPOINT: 'https://mock-orka-endpoint' ORKA_AUTH_TOKEN: 'mock-orka-auth-token' - SSH_DEFAULT_USERNAME: 'mock-ssh-default-username' - SSH_DEFAULT_PASSWORD: 'mock-ssh-default-password' - SSH_TEST_PASSWORD: 'mock-ssh-test-password' - SSH_RELEASE_PASSWORD: 'mock-ssh-release-password' - SSH_TEST_PUBLIC_KEY: 'mock-ssh-test-public-key' - SSH_RELEASE_PUBLIC_KEY: 'mock-ssh-release-public-key' + working-directory: orka/templates run: | for file in $(find . -name '*.pkr.hcl'); do echo "Validating $file" - vars="-var orka_endpoint=$ORKA_ENDPOINT -var orka_auth_token=$ORKA_AUTH_TOKEN -var ssh_default_username=$SSH_DEFAULT_USERNAME" - - if echo "$file" | grep -q "release"; then - vars="$vars -var ssh_release_password=$SSH_RELEASE_PASSWORD -var ssh_release_public_key=$SSH_RELEASE_PUBLIC_KEY" - elif echo "$file" | grep -q "test"; then - vars="$vars -var ssh_test_password=$SSH_TEST_PASSWORD -var ssh_test_public_key=$SSH_TEST_PUBLIC_KEY -var ssh_default_password=$SSH_DEFAULT_PASSWORD" - fi - - packer validate $vars $file || exit 1 - done - working-directory: orka/templates \ No newline at end of file + packer validate -var-file=variables.auto.pkrvars.hcl "$file" || exit 1 + done \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5aec6349e..653eedf44 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ ansible/host_vars/* Pipfile.lock # Orka secrets files including naming mutations -orka/*/.env* \ No newline at end of file +orka/*/.env* +/orka/templates/files/secrets/* +/orka/templates/*.pkrvars.hcl \ No newline at end of file diff --git a/ansible/inventory.yml b/ansible/inventory.yml index 8d70ac0c6..5b25de53f 100644 --- a/ansible/inventory.yml +++ b/ansible/inventory.yml @@ -200,6 +200,10 @@ hosts: ip: 172.16.9.3 ansible_ssh_common_args: '-o ProxyCommand="ssh -i ~/.ssh/nodejs_build_test -W %h:%p root@192.207.255.126"' ansible_user: root + smartos22-x64-3: + ip: 172.16.9.3 + ansible_ssh_common_args: '-o ProxyCommand="ssh -i ~/.ssh/nodejs_build_test -W %h:%p root@8.225.232.32"' + ansible_user: root smartos23-x64-4: ip: 172.16.9.3 ansible_ssh_common_args: '-o ProxyCommand="ssh -i ~/.ssh/nodejs_build_test -W %h:%p root@192.207.255.124"' @@ -208,6 +212,10 @@ hosts: ip: 172.16.9.3 ansible_ssh_common_args: '-o ProxyCommand="ssh -i ~/.ssh/nodejs_build_test -W %h:%p root@8.225.232.36"' ansible_user: root + smartos23-x64-6: + ip: 172.16.9.3 + ansible_ssh_common_args: '-o ProxyCommand="ssh -i ~/.ssh/nodejs_build_test -W %h:%p root@8.225.232.36"' + ansible_user: root - osuosl: diff --git a/orka/templates/README.md b/orka/templates/README.md index b689359f8..21f05def1 100644 --- a/orka/templates/README.md +++ b/orka/templates/README.md @@ -10,7 +10,7 @@ Once installed, you can verify the installation by running the following command packer --version ``` -While writing this document, the latest version of Packer is `1.11.2`. +While writing this document, the latest version of Packer is `1.14.2`. ## Install dependencies @@ -22,42 +22,65 @@ packer init . ## Access the Orka environment -You need to connect to the Orka VPN. You can find the instructions in the secrets repository. +1. You need to connect to the Orka VPN. You can find the instructions in the secrets repository. @TODO +2. Authenticate the cluster with `orka3 login` -> this will give a url to access to login to macstadium. This login lasts for 3600s. +3. Once logged into macstadium, you can `orka3 user get-token` to get a user token to do other things, like build images. -## Load the environment variables +## Authenticate to ghcr.io -You need to load the environment variables: +Some Macstadium base images are stored at ghcr.io (github's container registry). To allow packer to seamlessly pull +those images, you must provide the orka3 cli with a github personal access token (PAT). See [here]https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic +``` +orka3 regcred add https://ghcr.io --username GITHUB_USERNAME --password PAT_TOKEN +``` -1. Get the `.env` file from the secrets repository. You will find the instructions in the repository. -2. Copy the `.env` file to this directory. -3. Run the following command: - ```shell - source .env - ``` -4. Verify that the environment variables are loaded by running the following command: - ```shell - echo $ORKA_ENDPOINT - echo $ORKA_AUTH_TOKEN - echo $SSH_DEFAULT_USERNAME - echo $SSH_DEFAULT_PASSWORD - echo $SSH_TEST_PASSWORD - echo $SSH_TEST_PUBLIC_KEY - ``` +## Load the build variables + +You need to configure the variables.auto.pkrvars.hcl file + +1. Get the `orka.variables.auto.pkrvars.hcl` file from the secrets repository. There is one in release, and one in test +2. Copy the `orka.variables.auto.pkrvars.hcl` to `variables.auto.pkrvars.hcl` file to this directory. + +## Load the file secrets + +We need the private key for node-www for the release images, as well as the apple developer certificate for code signing. + +1. Copy the `secrets/build/release/staging_id_rsa_private.key` to orka/templates/files/secrets/id_rsa +2. Go to the `build/release` folder in the secrets repo +3. Extract from secrets/build/release and put it in this repo (adjust the orka path in this command): `dotgpg cat Apple\ Developer\ ID\ Node.js\ Foundation.p12.base64 | base64 -D > orka/templates/files/secrets/Apple\ Developer\ ID\ Node.js\ Foundation.p12` + +## Download Xcode to the shared vm storage + +1. Full Xcode installation + + Xcode Command-line tools are not enough to perform a full notarization cycle, full Xcode must be fully installed on the release images. + + * Login to https://developer.apple.com using the apple-operations@openjsf.org account + * Download Xcode: https://developer.apple.com/download/more/ - find non-beta version, open Developer Tools in browser, Networking tab, start download (then cancel), in Networking tab "Copy as cURL" (available in Chrome & FF) + * On OSX 15 we currently install 16.4 + * Manually launch one of the existing VM's (Arm ones are faster) + * `orka3 images list` to see available images + * `orka3 vm deploy --image IMAGE_NAME` to deploy a new image + * NOTE: don't try to connect to an existing image as jenkins may delete it while you're working on it. + * Connect to the VM with ssh, and navigate to /Volumes/orka/Xcode + * use orkaconnect.sh VM_NAME (ie. `orkaconnect.sh vm-h1tcv`) + * Execute the curl command to download Xcode, save it to a file named Xcode_{VERSION}.xip i.e. Xcode_16.4.xip + * This is where packer will look when installing xcode in the image. ## Validate the template -You can validate a specific template by running the following command: +You can validate a specific template by running the following command (replace test with release if doing release images) ```shell -packer validate -var "orka_endpoint=$ORKA_ENDPOINT" -var "orka_auth_token=$ORKA_AUTH_TOKEN" -var "ssh_default_username=$SSH_DEFAULT_USERNAME" -var "ssh_default_password=$SSH_DEFAULT_PASSWORD" -var "ssh_test_password=$SSH_TEST_PASSWORD" -var "ssh_release_password=$SSH_RELEASE_PASSWORD" -var "ssh_release_public_key=$SSH_RELEASE_PUBLIC_KEY" -var "ssh_test_public_key=$SSH_TEST_PUBLIC_KEY" -``` +ORKA_AUTH_TOKEN=$(orka3 user get-token) packer validate -var-file=variables.auto.pkrvars.hcl macos-test.pkr.hcl + ``` ## Build the image You can build a specific template by running the following command: ```shell -packer build -var "orka_endpoint=$ORKA_ENDPOINT" -var "orka_auth_token=$ORKA_AUTH_TOKEN" -var "ssh_default_username=$SSH_DEFAULT_USERNAME" -var "ssh_default_password=$SSH_DEFAULT_PASSWORD" -var "ssh_test_password=$SSH_TEST_PASSWORD" -var "ssh_release_password=$SSH_RELEASE_PASSWORD" -var "ssh_release_public_key=$SSH_RELEASE_PUBLIC_KEY" -var "ssh_test_public_key=$SSH_TEST_PUBLIC_KEY" +ORKA_AUTH_TOKEN=$(orka3 user get-token) packer build -var-file=variables.auto.pkrvars.hcl macos-test.pkr.hcl ``` ## Continuous Integration @@ -70,6 +93,8 @@ We don't plan to build the images in the CI pipeline. The images are built manua Orka provides a base image that we need to customize to our needs. +Note that orka3 remote-image command is only for interacting with x64 images. arm64 images are at ghcr.io: https://github.com/macstadium/orka-images + 1. find the image that you want to extend by running the following command: ```shell orka3 remote-image list @@ -95,130 +120,3 @@ Orka provides a base image that we need to customize to our needs. orka3 vm delete ``` Note: Don't delete the vm until you have saved the image, check by running the command `orka3 image list` - - - -### Manual Steps for all the images - -1. Update Sudoers file: - -this requires `NOPASSWD` to be added to the sudoers file to enable elevation - -`sudo visudo` -and change: -`%admin ALL = (ALL) ALL` -to -`%admin ALL = (ALL) NOPASSWD:ALL` - -2. Allow ssh access - -```bash -sudo systemsetup -setremotelogin on -``` -3. Install xcode - -```bash -sudo xcode-select --install -``` - -Do a an update using the UI. Check the available updates and install them (click in "more info"). Note that you don't want to update the OS, just the software. - -### Manual Steps for the release images - -1. Full Xcode installation - - Xcode Command-line tools are not enough to perform a full notarization cycle, full Xcode must be installed manually. - - As root: - - * Download Xcode: https://developer.apple.com/download/more/ - find non-beta version, open Developer Tools in browser, Networking tab, start download (then cancel), in Networking tab "Copy as cURL" (available in Chrome & FF) - * On OSX 13 we currently install 14.13.1. - * Go to downloads folder, decompress the xip file (double click) and delete the xip file - * Move the Xcode.app to /Applications - * Open xcode, accept the license, install the built-in components and close xcode - * `sudo xcode-select --switch /Applications/Xcode.app` - * `sudo xcodebuild -license` - accept license - * `git` - check that git is working (confirming license has been accepted) - * Empty the trash - - -2. OSX Keychain Profile - - Unblok the keychain: - - ```bash - security unlock-keychain -u /Library/Keychains/System.keychain - ``` - - Create a keychain profile (`NODE_RELEASE_PROFILE`) for the release machine: - - ```bash - sudo xcrun notarytool store-credentials NODE_RELEASE_PROFILE \ - --apple-id XXXX \ - --team-id XXXX \ - --password XXXX \ - --keychain /Library/Keychains/System.keychain - ``` - - Note: `XXXX` values are found in `secrets/build/release/apple.md` - - The expected output is: - - ``` - This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name. - - Validating your credentials... - Success. Credentials validated. - Credentials saved to Keychain. - To use them, specify `--keychain-profile "NODE_RELEASE_PROFILE" --keychain /Library/Keychains/System.keychain` - ``` - -3. Signing certificates - - * Go to the `build/release` folder in the secrets repo. - * Extract from secrets/build/release: `dotgpg cat Apple\ Developer\ ID\ Node.js\ Foundation.p12.base64 | base64 -D > /tmp/Apple\ Developer\ ID\ Node.js\ Foundation.p12` - * Transfer to release machine (scp to /tmp) - * `sudo security import /tmp/Apple\ Developer\ ID\ Node.js\ Foundation.p12 -k /Library/Keychains/System.keychain -T /usr/bin/codesign -T /usr/bin/productsign -P 'XXXX'` (where XXXX is found in secrets/build/release/apple.md) (`security unlock-keychain -u /Library/Keychains/System.keychain` _may_ be required prior to running this command). - -4. Validating certificates are in date and valid - - 1. `security -i unlock-keychain` Enter the password for the machine located in secrets - 2. `security find-certificate -c "Developer ID Application" -p > /tmp/app.cert` outputs the PEM format of the cert so we can properly inspect it - 3. `security find-certificate -c "Developer ID Installer" -p > /tmp/installer.cert` - 4. `openssl x509 -inform PEM -text -in /tmp/app.cert | less` - 5. `openssl x509 -inform PEM -text -in /tmp/installer.cert | less` - 6. `security find-identity -p codesigning -v` - - The steps 4 and 5 will show the details of the certificates allowing to see expiry dates. - - Example: - - ``` - Not Before: Jan 22 03:40:05 2020 GMT - Not After : Jan 22 03:40:05 2025 GMT - ``` - - The step 6 will show the list of certificates available on the machine. - - Example: - - ``` - 1) XXXXXXXXXXX "Developer ID Application: Node.js Foundation (XXXXXXX)" - 1 valid identities found - ``` - -5. Change the default password - - Use the password found in the secrets repository to change the default password: - - ```shell - passwd - ``` - - Also change the keychain password: - - ```shell - security set-keychain-password - ``` - - **:warning: IMPORTANT** We do this step manually at this point and not while using Packer because we added already sensitive information to the image. \ No newline at end of file diff --git a/orka/templates/files/admin_uid_change.sh b/orka/templates/files/admin_uid_change.sh new file mode 100644 index 000000000..ed57db2d6 --- /dev/null +++ b/orka/templates/files/admin_uid_change.sh @@ -0,0 +1,12 @@ +#!/bin/bash +source /Users/admin/.zprofile +if [ $IMAGE_ARCHITECTURE = x64 ]; then + echo "Re-numerating admin account. This takes a while to chmod" + dscl . -change /Users/admin UniqueID 501 107 + time find /Users/admin -uid 501 -exec chown -h 107 {} \; + dscl . create /Groups/ci + dscl . create /Groups/ci gid 107 + dscl . create /Groups/ci passwd '*' + dscl . create /Groups/ci GroupMembership admin + echo "Finally done." +fi \ No newline at end of file diff --git a/orka/templates/files/com.mount9p.plist b/orka/templates/files/com.mount9p.plist new file mode 100644 index 000000000..81b5d7685 --- /dev/null +++ b/orka/templates/files/com.mount9p.plist @@ -0,0 +1,20 @@ + + + + + Label + com.mount9p.plist + RunAtLoad + + StandardErrorPath + /var/log/mount_9p_error.log + StandardOutPath + /var/log/mount_9p.log + ProgramArguments + + /bin/bash + -c + mkdir -p /Volumes/orka && mount_9p orka + + + diff --git a/orka/templates/files/ssh_config.txt b/orka/templates/files/ssh_config.txt new file mode 100644 index 000000000..e2ab8d7b4 --- /dev/null +++ b/orka/templates/files/ssh_config.txt @@ -0,0 +1,4 @@ +Host node-www + HostName direct.nodejs.org + User staging + IdentityFile ~/.ssh/id_rsa \ No newline at end of file diff --git a/orka/templates/files/update_xcode.sh b/orka/templates/files/update_xcode.sh new file mode 100644 index 000000000..4e38207df --- /dev/null +++ b/orka/templates/files/update_xcode.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e + +XCODE_VERSION=$1 + +if [[ -n $DEBUG ]]; then + set -x +fi + +cd ~/Desktop +cp /Volumes/orka/Xcode/Xcode_${XCODE_VERSION}.xip ~/Desktop/Xcode.xip + +if [ ! -d Xcode.app ]; then + echo "Unpacking… This will take several minutes" + xip --expand Xcode.xip +fi + +if [ -d /Applications/Xcode.app ]; then + echo "Removing old Xcode" + rm -rf /Applications/Xcode.app +fi + +echo "Moving new Xcode into place" +mv Xcode.app /Applications + +sudo xcode-select -s /Applications/Xcode.app + +echo "Accepting the license agreement" +sudo xcodebuild -license accept + +echo "Installing internal packages to avoid the first launch prompt" +sudo xcodebuild -runFirstLaunch + +sudo DevToolsSecurity -enable + +rm -f Xcode.xip + +echo "Done!" diff --git a/orka/templates/macos-13-arm-release.pkr.hcl b/orka/templates/macos-13-arm-release.pkr.hcl deleted file mode 100644 index d439c0f36..000000000 --- a/orka/templates/macos-13-arm-release.pkr.hcl +++ /dev/null @@ -1,148 +0,0 @@ -variable "orka_endpoint" { - type = string - default = "" -} - -variable "orka_auth_token" { - type = string - default = "" -} - -variable "ssh_default_username" { - type = string - default = "" -} - -variable "ssh_default_password" { - type = string - default = "" -} - -variable "ssh_release_public_key" { - type = string - default = "" -} - -variable "ssh_release_password" { - type = string - default = "" -} - -packer { - required_plugins { - macstadium-orka = { - version = "~> 3.0" - source = "github.com/macstadium/macstadium-orka" - } - } -} - -source "macstadium-orka" "macos13-arm-release-image" { - source_image = "macos13-arm-release-base.orkasi" - image_name = "macos13-arm-release-latest.orkasi" - image_description = "The MacOS 13 ARM release image" - orka_endpoint = var.orka_endpoint - orka_auth_token = var.orka_auth_token - ssh_username = var.ssh_default_username - ssh_password = var.ssh_release_password -} - -build { - sources = [ - "macstadium-orka.macos13-arm-release-image" - ] - - // Add SSH key access. - provisioner "shell" { - inline = [ - "echo 'Adding SSH key access...'", - "mkdir -p /Users/${var.ssh_default_username}/.ssh", - "echo '${var.ssh_release_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", - "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", - "chmod 700 /Users/${var.ssh_default_username}/.ssh", - "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" - ] - } - // Add GitHub host key to known hosts. - provisioner "shell" { - inline = [ - "echo 'Adding GitHub host key to known hosts...'", - "ssh-keyscan github.com >> /Users/${var.ssh_default_username}/.ssh/known_hosts" - ] - } - // Disable SSH password authentication. - // @TODO: Review fallback to password authentication. - provisioner "shell" { - inline = [ - "echo 'Disabling SSH password authentication...'", - "sudo sed -i '' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo systemsetup -f -setremotelogin on", - "sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist", - "sudo launchctl load /System/Library/LaunchDaemons/ssh.plist", - ] - } - - // Install Homebrew. - provisioner "shell" { - inline = [ - "echo 'Installing Homebrew...'", - "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "(echo; echo 'eval \"$($(brew --prefix)/bin/brew shellenv)\"') >> /Users/admin/.zprofile", - "eval \"$($(brew --prefix)/bin/brew shellenv)\"" - ] - } - // Ensure Homebrew environment is set up in the shell profile. - provisioner "shell" { - inline = [ - "echo 'Setting up Homebrew environment in shell profile...'", - "echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users/admin/.zshrc", - "echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users/admin/.bash_profile" - ] - } - // Check Homebrew. Ignore errors because we are not using the last version of Xcode. - provisioner "shell" { - inline = [ - "echo 'Checking Homebrew...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew doctor || true" - ] - } - // Install dependencies for build and release. - provisioner "shell" { - inline = [ - "echo 'Installing packages using Homebrew...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew install git automake bash libtool cmake python ccache xz" - ] - } - // Install tap2junit using pip. - provisioner "shell" { - inline = [ - "echo 'Installing tap2junit using pip...'", - "python3 -m pip install --user tap2junit", - "export PATH=$PATH:/Users/admin/.local/bin" - ] - } - // Install Java 17 for Jenkins. - provisioner "shell" { - inline = [ - "echo 'Installing JRE...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew install --cask temurin@17", - ] - } - // Print the version of the installed packages. - provisioner "shell" { - inline = [ - "echo 'Printing the version of the installed packages...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew list --versions", - "java -version", - "xcodebuild -version" - ] - } -} \ No newline at end of file diff --git a/orka/templates/macos-13-arm-test.pkr.hcl b/orka/templates/macos-13-arm-test.pkr.hcl deleted file mode 100644 index d0a95e899..000000000 --- a/orka/templates/macos-13-arm-test.pkr.hcl +++ /dev/null @@ -1,155 +0,0 @@ -variable "orka_endpoint" { - type = string - default = "" -} - -variable "orka_auth_token" { - type = string - default = "" -} - -variable "ssh_default_username" { - type = string - default = "" -} - -variable "ssh_default_password" { - type = string - default = "" -} - -variable "ssh_test_public_key" { - type = string - default = "" -} - -variable "ssh_test_password" { - type = string - default = "" -} - -packer { - required_plugins { - macstadium-orka = { - version = "~> 3.0" - source = "github.com/macstadium/macstadium-orka" - } - } -} - -source "macstadium-orka" "macos13-arm-test-image" { - source_image = "macos13-arm-base.orkasi" - image_name = "macos13-arm-test-latest.orkasi" - image_description = "The MacOS 13 ARM test image" - orka_endpoint = var.orka_endpoint - orka_auth_token = var.orka_auth_token - ssh_username = var.ssh_default_username - ssh_password = var.ssh_default_password -} - -build { - sources = [ - "macstadium-orka.macos13-arm-test-image" - ] - // Change the password of the default user. - provisioner "shell" { - inline = [ - "echo 'Changing default user password...'", - "sudo sysadminctl -adminUser ${var.ssh_default_username} -adminPassword ${var.ssh_default_password} -resetPasswordFor ${var.ssh_default_username} -newPassword ${var.ssh_test_password}" - ] - } - // Add SSH key access. - provisioner "shell" { - inline = [ - "echo 'Adding SSH key access...'", - "mkdir -p /Users/${var.ssh_default_username}/.ssh", - "echo '${var.ssh_test_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", - "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", - "chmod 700 /Users/${var.ssh_default_username}/.ssh", - "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" - ] - } - // Add GitHub host key to known hosts. - provisioner "shell" { - inline = [ - "echo 'Adding GitHub host key to known hosts...'", - "ssh-keyscan github.com >> /Users/${var.ssh_default_username}/.ssh/known_hosts" - ] - } - // Disable SSH password authentication. - // @TODO: Review fallback to password authentication. - provisioner "shell" { - inline = [ - "echo 'Disabling SSH password authentication...'", - "sudo sed -i '' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo systemsetup -f -setremotelogin on", - "sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist", - "sudo launchctl load /System/Library/LaunchDaemons/ssh.plist", - ] - } - - // Install Homebrew. - provisioner "shell" { - inline = [ - "echo 'Installing Homebrew...'", - "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "(echo; echo 'eval \"$($(brew --prefix)/bin/brew shellenv)\"') >> /Users/admin/.zprofile", - "eval \"$($(brew --prefix)/bin/brew shellenv)\"" - ] - } - // Ensure Homebrew environment is set up in the shell profile. - provisioner "shell" { - inline = [ - "echo 'Setting up Homebrew environment in shell profile...'", - "echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users/admin/.zshrc", - "echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users/admin/.bash_profile" - ] - } - // Check Homebrew. Ignore errors because we are not using the last version of Xcode. - provisioner "shell" { - inline = [ - "echo 'Checking Homebrew...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew doctor || true" - ] - } - // Install dependencies for build and test. - provisioner "shell" { - inline = [ - "echo 'Installing packages using Homebrew...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew install git automake bash libtool cmake python ccache xz" - ] - } - // Install tap2junit using pip. - provisioner "shell" { - inline = [ - "echo 'Installing tap2junit using pip...'", - "python3 -m pip install --user tap2junit", - "export PATH=$PATH:/Users/admin/.local/bin" - ] - } - // Install Java 17 for Jenkins. - provisioner "shell" { - inline = [ - "echo 'Installing JRE...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew install --cask temurin@17", - ] - } - // Print the version of the installed packages. - provisioner "shell" { - inline = [ - "echo 'Printing the version of the installed packages...'", - "eval \"$(/opt/homebrew/bin/brew shellenv)\"", - "/opt/homebrew/bin/brew list --versions", - "java -version", - // @TODO: Solve the problem with the Xcode version. - //"xcodebuild -version" - ] - } -} \ No newline at end of file diff --git a/orka/templates/macos-13-intel-release.pkr.hcl b/orka/templates/macos-13-intel-release.pkr.hcl deleted file mode 100644 index 92701134d..000000000 --- a/orka/templates/macos-13-intel-release.pkr.hcl +++ /dev/null @@ -1,146 +0,0 @@ -variable "orka_endpoint" { - type = string - default = "" -} - -variable "orka_auth_token" { - type = string - default = "" -} - -variable "ssh_default_username" { - type = string - default = "" -} - -variable "ssh_default_password" { - type = string - default = "" -} - -variable "ssh_release_public_key" { - type = string - default = "" -} - -variable "ssh_release_password" { - type = string - default = "" -} - -packer { - required_plugins { - macstadium-orka = { - version = "~> 3.0" - source = "github.com/macstadium/macstadium-orka" - } - } -} - -source "macstadium-orka" "macos13-intel-release-image" { - source_image = "macos13-intel-release-base.img" - image_name = "macos13-intel-release-latest.img" - image_description = "The MacOS 13 Intel release image" - orka_endpoint = var.orka_endpoint - orka_auth_token = var.orka_auth_token - ssh_username = var.ssh_default_username - ssh_password = var.ssh_release_password -} - -build { - sources = [ - "macstadium-orka.macos13-intel-release-image" - ] - // Add SSH key access. - provisioner "shell" { - inline = [ - "echo 'Adding SSH key access...'", - "mkdir -p /Users/${var.ssh_default_username}/.ssh", - "echo '${var.ssh_release_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", - "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", - "chmod 700 /Users/${var.ssh_default_username}/.ssh", - "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" - ] - } - // Add GitHub host key to known hosts. - provisioner "shell" { - inline = [ - "echo 'Adding GitHub host key to known hosts...'", - "ssh-keyscan github.com >> /Users/${var.ssh_default_username}/.ssh/known_hosts" - ] - } - // Disable SSH password authentication. - // @TODO: Review fallback to password authentication. - provisioner "shell" { - inline = [ - "echo 'Disabling SSH password authentication...'", - "sudo sed -i '' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo systemsetup -f -setremotelogin on", - "sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist", - "sudo launchctl load /System/Library/LaunchDaemons/ssh.plist", - ] - } - // Install Homebrew. - provisioner "shell" { - inline = [ - "echo 'Installing Homebrew...'", - "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "(echo; echo 'eval \"$($(brew --prefix)/bin/brew shellenv)\"') >> /Users/admin/.zprofile", - "eval \"$($(brew --prefix)/bin/brew shellenv)\"" - ] - } - // Ensure Homebrew environment is set up in the shell profile. - provisioner "shell" { - inline = [ - "echo 'Setting up Homebrew environment in shell profile...'", - "echo 'eval \"$(/usr/local/bin/brew shellenv)\"' >> /Users/admin/.zshrc", - "echo 'eval \"$(/usr/local/bin/brew shellenv)\"' >> /Users/admin/.bash_profile" - ] - } - // Check Homebrew. Ignore errors because we are not using the last version of Xcode. - provisioner "shell" { - inline = [ - "echo 'Checking Homebrew...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew doctor || true" - ] - } - // Install dependencies for build and release. - provisioner "shell" { - inline = [ - "echo 'Installing packages using Homebrew...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew install git automake bash libtool cmake python ccache xz" - ] - } - // Install tap2junit using pip. - provisioner "shell" { - inline = [ - "echo 'Installing tap2junit using pip...'", - "python3 -m pip install --user tap2junit", - "export PATH=$PATH:/Users/admin/.local/bin" - ] - } - // Install Java 17 for Jenkins. - provisioner "shell" { - inline = [ - "echo 'Installing JRE...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew install --cask temurin@17", - ] - } - // Print the version of the installed packages. - provisioner "shell" { - inline = [ - "echo 'Printing the version of the installed packages...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew list --versions", - "java -version", - "xcodebuild -version" - ] - } -} \ No newline at end of file diff --git a/orka/templates/macos-13-intel-test.pkr.hcl b/orka/templates/macos-13-intel-test.pkr.hcl deleted file mode 100644 index e271a98fd..000000000 --- a/orka/templates/macos-13-intel-test.pkr.hcl +++ /dev/null @@ -1,154 +0,0 @@ -variable "orka_endpoint" { - type = string - default = "" -} - -variable "orka_auth_token" { - type = string - default = "" -} - -variable "ssh_default_username" { - type = string - default = "" -} - -variable "ssh_default_password" { - type = string - default = "" -} - -variable "ssh_test_public_key" { - type = string - default = "" -} - -variable "ssh_test_password" { - type = string - default = "" -} - -packer { - required_plugins { - macstadium-orka = { - version = "~> 3.0" - source = "github.com/macstadium/macstadium-orka" - } - } -} - -source "macstadium-orka" "macos13-intel-test-image" { - source_image = "macos13-intel-base.img" - image_name = "macos13-intel-test-latest.img" - image_description = "The MacOS 13 Intel test image" - orka_endpoint = var.orka_endpoint - orka_auth_token = var.orka_auth_token - ssh_username = var.ssh_default_username - ssh_password = var.ssh_default_password -} - -build { - sources = [ - "macstadium-orka.macos13-intel-test-image" - ] - // Change the password of the default user. - provisioner "shell" { - inline = [ - "echo 'Changing default user password...'", - "sudo sysadminctl -adminUser ${var.ssh_default_username} -adminPassword ${var.ssh_default_password} -resetPasswordFor ${var.ssh_default_username} -newPassword ${var.ssh_test_password}" - ] - } - // Add SSH key access. - provisioner "shell" { - inline = [ - "echo 'Adding SSH key access...'", - "mkdir -p /Users/${var.ssh_default_username}/.ssh", - "echo '${var.ssh_test_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", - "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", - "chmod 700 /Users/${var.ssh_default_username}/.ssh", - "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" - ] - } - // Add GitHub host key to known hosts. - provisioner "shell" { - inline = [ - "echo 'Adding GitHub host key to known hosts...'", - "ssh-keyscan github.com >> /Users/${var.ssh_default_username}/.ssh/known_hosts" - ] - } - // Disable SSH password authentication. - // @TODO: Review fallback to password authentication. - provisioner "shell" { - inline = [ - "echo 'Disabling SSH password authentication...'", - "sudo sed -i '' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo sed -i '' 's/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", - "sudo systemsetup -f -setremotelogin on", - "sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist", - "sudo launchctl load /System/Library/LaunchDaemons/ssh.plist", - ] - } - // Install Homebrew. - provisioner "shell" { - inline = [ - "echo 'Installing Homebrew...'", - "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "(echo; echo 'eval \"$($(brew --prefix)/bin/brew shellenv)\"') >> /Users/admin/.zprofile", - "eval \"$($(brew --prefix)/bin/brew shellenv)\"" - ] - } - // Ensure Homebrew environment is set up in the shell profile. - provisioner "shell" { - inline = [ - "echo 'Setting up Homebrew environment in shell profile...'", - "echo 'eval \"$(/usr/local/bin/brew shellenv)\"' >> /Users/admin/.zshrc", - "echo 'eval \"$(/usr/local/bin/brew shellenv)\"' >> /Users/admin/.bash_profile" - ] - } - // Check Homebrew. Ignore errors because we are not using the last version of Xcode. - provisioner "shell" { - inline = [ - "echo 'Checking Homebrew...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew doctor || true" - ] - } - // Install dependencies for build and test. - provisioner "shell" { - inline = [ - "echo 'Installing packages using Homebrew...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew install git automake bash libtool cmake python ccache xz" - ] - } - // Install tap2junit using pip. - provisioner "shell" { - inline = [ - "echo 'Installing tap2junit using pip...'", - "python3 -m pip install --user tap2junit", - "export PATH=$PATH:/Users/admin/.local/bin" - ] - } - // Install Java 17 for Jenkins. - provisioner "shell" { - inline = [ - "echo 'Installing JRE...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew install --cask temurin@17", - ] - } - // Print the version of the installed packages. - provisioner "shell" { - inline = [ - "echo 'Printing the version of the installed packages...'", - "eval \"$(/usr/local/bin/brew shellenv)\"", - "/usr/local/bin/brew list --versions", - "java -version", - // @TODO: Solve the problem with the Xcode version. - //"xcodebuild -version" - ] - } -} \ No newline at end of file diff --git a/orka/templates/macos-release.pkr.hcl b/orka/templates/macos-release.pkr.hcl new file mode 100644 index 000000000..140bf03d9 --- /dev/null +++ b/orka/templates/macos-release.pkr.hcl @@ -0,0 +1,237 @@ +variable "orka_endpoint" { + type = string + default = "http://10.221.190.20" +} + +variable "orka_auth_token" { + type = string + default = env("ORKA_AUTH_TOKEN") + sensitive = true +} +# TODO document how to put this into an environment variable +# orka3 login;ORKA_AUTH_TOKEN=$(orka3 user get-token) + +variable "orka_source_image" { + type = string + default = "ghcr.io/macstadium/orka-images/sequoia:15.4.1-no-sip" +} + +variable "image_type" { + type = string + default = "test" + + validation { + condition = contains(["test", "release"], var.image_type) + error_message = "Image_type must be either test or release." + } +} + +variable "macos_version" { + type = string + default = "" +} + +variable "xcode_version" { + type = string + default = null +} + +variable "ssh_default_username" { + type = string + default = "admin" +} + +# The password to access the image via ssh +variable "ssh_image_password" { + type = string + default = "admin" + sensitive = true +} + +# The public key we will put on the image for future access +variable "ssh_new_public_key" { + type = string + default = "" +} + +# The password that gets assigned to the image for future access +variable "ssh_new_password" { + type = string + default = "" + sensitive = true +} + +variable "architecture" { + type = string + default = "arm64" + description = "Target architecture for the build (arm64 or x64)" + + validation { + condition = contains(["arm64", "x64"], var.architecture) + error_message = "Architecture must be either arm64 or x64." + } +} + +variable "homebrew_path_map" { + type = map(string) + default = { + "arm64" = "/opt/homebrew" + "x64" = "/usr/local" + } +} + +# The password that gets assigned to the image for future access +variable "apple_signing_password" { + type = string + default = "" + sensitive = true +} + +locals { + build_timestamp = formatdate("YYMMDDHHMMss", timestamp()) +} + +locals { + homebrew_path = lookup(var.homebrew_path_map, var.architecture, "arm64") +} + +packer { + required_plugins { + macstadium-orka = { + version = "~> 3.0" + source = "github.com/macstadium/macstadium-orka" + } + } +} + +source "macstadium-orka" "orka-image" { + source_image = var.orka_source_image + image_name = "macos-${var.macos_version}-${var.architecture}-${var.image_type}-${local.build_timestamp}" + image_description = "The MacOS ${var.macos_version} ${var.architecture} ${var.image_type} image" + orka_endpoint = var.orka_endpoint + orka_auth_token = var.orka_auth_token + ssh_username = var.ssh_default_username + ssh_password = var.ssh_image_password + //no_create_image = true + //no_delete_vm = true +} + + +# The release images are based on the test images. +build { + name = "release" + + sources = [ + "macstadium-orka.orka-image" + ] + + // Change the password of the default user. + provisioner "shell" { + inline = [ + "echo 'Setting user password...'", + "sudo sysadminctl -adminUser ${var.ssh_default_username} -adminPassword ${var.ssh_image_password} -resetPasswordFor ${var.ssh_default_username} -newPassword ${var.ssh_new_password}" + ] + } + // Set system hostname. + provisioner "shell" { + inline = [ + "echo 'Setting system hostname...'", + "sudo scutil --set HostName macos-${var.macos_version}-${var.architecture}-release" + ] + } + // Change ssh key to the release key to reduce the number of amount of granted access. + provisioner "shell" { + inline = [ + "echo 'Adding SSH key access...'", + "echo '${var.ssh_new_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", + "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", + "chmod 700 /Users/${var.ssh_default_username}/.ssh", + "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" + ] + } + + // Add direct.nodejs.org host key to known hosts. + provisioner "shell" { + inline = [ + "echo 'Adding direct.nodejs.org host key to known hosts...'", + "ssh-keyscan direct.nodejs.org >> /Users/${var.ssh_default_username}/.ssh/known_hosts" + ] + } + + + + // Set the default keychain password and unlock it + provisioner "shell" { + inline = [ + "echo 'Setting default keychain password'", + "security set-keychain-password -o admin -p ${var.ssh_new_password}", + "security unlock-keychain -p ${var.ssh_new_password}", + ] + } + + + // Configure Notarytool to use the nodejs profile + provisioner "shell" { + inline = [ + "echo 'Configuring notarytool profile'", + "security unlock-keychain -u /Library/Keychains/System.keychain", + "sudo xcrun notarytool store-credentials NODE_RELEASE_PROFILE --apple-id apple-operations@openjsf.org --team-id HX7739G8FX --password ${var.apple_signing_password} --keychain /Library/Keychains/System.keychain" + ] + }// Configure Notarytool to use the nodejs profile + provisioner "shell" { + inline = [ + "security unlock-keychain -p ${var.ssh_new_password}", + "echo 'Proving notarytool works'", + "xcrun notarytool history --keychain-profile NODE_RELEASE_PROFILE" + ] + } + + # Upload cert file + provisioner "file" { + source = "files/secrets/Apple Developer ID Node.js Foundation.p12" + destination = "/tmp/applecert.p12" + } + + # Add ssh config for node-www + provisioner "file" { + source = "files/ssh_config.txt" + destination = "/Users/admin/.ssh/config" + } + + # Add id_rsa key so builds can publish to node-www + provisioner "file" { + source = "files/secrets/id_rsa" + destination = "/Users/admin/.ssh/id_rsa" + } + # Fix permissions on id_rsa (must be 600 for SSH to use it) + provisioner "shell" { + inline = [ + "chmod 600 /Users/admin/.ssh/id_rsa" + ] + } + + provisioner "shell" { + inline = [ + "security unlock-keychain -p ${var.ssh_new_password}", + "sudo security import /tmp/applecert.p12 -k /Library/Keychains/System.keychain -P ${var.apple_signing_password} -T /usr/bin/codesign -T /usr/bin/productsign" + ] + } + + // Install rosetta on arm images so we can build universal binaries. + provisioner "shell" { + inline = [ + "source /Users/admin/.zprofile", + "if [ $IMAGE_ARCHITECTURE = arm64 ]; then", + "sudo /usr/sbin/softwareupdate --install-rosetta --agree-to-license", + "else", + "echo 'Skipping rosetta installation'", + "fi" + ] + } + // Xcode versions should be manually downloaded to (example) /Volumes/orka/xcode/Xcode_16.4.xip + provisioner "shell" { + script = "files/update_xcode.sh" + execute_command = "chmod +x {{ .Path }}; sudo -E sh {{ .Path }} ${var.xcode_version}" + } + +} diff --git a/orka/templates/macos-test.pkr.hcl b/orka/templates/macos-test.pkr.hcl new file mode 100644 index 000000000..73dad2244 --- /dev/null +++ b/orka/templates/macos-test.pkr.hcl @@ -0,0 +1,312 @@ +variable "orka_endpoint" { + type = string + default = "http://10.221.190.20" +} + +variable "orka_auth_token" { + type = string + default = env("ORKA_AUTH_TOKEN") + sensitive = true +} +# TODO document how to put this into an environment variable +# orka3 login;ORKA_AUTH_TOKEN=$(orka3 user get-token) + +variable "orka_source_image" { + type = string + default = "ghcr.io/macstadium/orka-images/sequoia:15.4.1-no-sip" +} + +variable "image_type" { + type = string + default = "test" + + validation { + condition = contains(["test", "release"], var.image_type) + error_message = "Image_type must be either test or release." + } +} + +variable "macos_version" { + type = string + default = "15.4.1" +} + +variable "xcode_version" { + type = string + default = "16.4" +} + + +variable "ssh_default_username" { + type = string + default = "admin" +} + +variable "ssh_image_password" { + type = string + default = "admin" + sensitive = true +} + +variable "ssh_new_public_key" { + type = string + default = "" +} + +variable "ssh_new_password" { + type = string + default = "" + sensitive = true +} + +variable "architecture" { + type = string + default = "arm64" + description = "Target architecture for the build (arm64 or x64)" + + validation { + condition = contains(["arm64", "x64"], var.architecture) + error_message = "Architecture must be either arm64 or x64." + } +} + +variable "homebrew_path_map" { + type = map(string) + default = { + "arm64" = "/opt/homebrew" + "x64" = "/usr/local" + } +} + +locals { + build_timestamp = formatdate("YYMMDDHHMMss", timestamp()) +} + +locals { + homebrew_path = lookup(var.homebrew_path_map, var.architecture, "arm64") +} + +packer { + required_plugins { + macstadium-orka = { + version = "~> 3.0" + source = "github.com/macstadium/macstadium-orka" + } + } +} + +source "macstadium-orka" "orka-image" { + source_image = var.orka_source_image + image_name = "macos-${var.macos_version}-${var.architecture}-${var.image_type}-${local.build_timestamp}" + image_description = "The MacOS ${var.macos_version} ${var.architecture} ${var.image_type} image" + orka_endpoint = var.orka_endpoint + orka_auth_token = var.orka_auth_token + ssh_username = var.ssh_default_username + ssh_password = var.ssh_image_password + //no_create_image = true +} + + +# We build the test image first, then, use the same image to add what we need to the release image. +build { + name = "test" + + sources = [ + "macstadium-orka.orka-image" + ] + + // Allow admin to sudo without a password + provisioner "shell" { + inline = [ + "echo 'Setting the image type for future shell commands'", + "echo 'export IMAGE_ARCHITECTURE=\"${var.architecture}\"' >> /Users/admin/.zprofile" + ] + } + + + // Allow admin to sudo without a password + provisioner "shell" { + inline = [ + "echo 'Allowing sudo without password...'", + "echo ${var.ssh_image_password} | sudo -S id", + "echo ${var.ssh_image_password} | sudo -S tee /private/etc/sudoers.d/90-nopasswd-admin > /dev/null <<< '%admin ALL=(ALL) NOPASSWD:ALL'", + "echo ${var.ssh_image_password} | sudo -S chmod 0440 /private/etc/sudoers.d/90-nopasswd-admin", + "echo ${var.ssh_image_password} | sudo -S visudo -c" + ] + } + // Change the password of the default user. + provisioner "shell" { + inline = [ + "echo 'Setting user password...'", + "sudo sysadminctl -adminUser ${var.ssh_default_username} -adminPassword ${var.ssh_image_password} -resetPasswordFor ${var.ssh_default_username} -newPassword ${var.ssh_new_password}" + ] + } + // Set system hostname. + provisioner "shell" { + inline = [ + "echo 'Setting system hostname...'", + "sudo scutil --set HostName macos-${var.macos_version}-${var.architecture}-test" + ] + } + // Add SSH key access. + provisioner "shell" { + inline = [ + "echo 'Adding SSH key access...'", + "mkdir -p /Users/${var.ssh_default_username}/.ssh", + "echo '${var.ssh_new_public_key}' >> /Users/${var.ssh_default_username}/.ssh/authorized_keys", + "chown -R ${var.ssh_default_username}:staff /Users/${var.ssh_default_username}/.ssh", + "chmod 700 /Users/${var.ssh_default_username}/.ssh", + "chmod 600 /Users/${var.ssh_default_username}/.ssh/authorized_keys" + ] + } + // Add GitHub host key to known hosts. + provisioner "shell" { + inline = [ + "echo 'Adding GitHub host key to known hosts...'", + "ssh-keyscan github.com >> /Users/${var.ssh_default_username}/.ssh/known_hosts" + ] + } + // Disable SSH password authentication. + // @TODO: Review fallback to password authentication. + provisioner "shell" { + inline = [ + "echo 'Disabling SSH password authentication...'", + "sudo sed -i '' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", + "sudo sed -i '' 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config", + "sudo sed -i '' 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config", + "sudo sed -i '' 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", + "sudo sed -i '' 's/^ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config", + "sudo systemsetup -f -setremotelogin on", + "sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist", + "sudo launchctl load /System/Library/LaunchDaemons/ssh.plist", + ] + } + + // Install Homebrew. + provisioner "shell" { + inline = [ + "echo 'Installing Homebrew...'", + "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "(echo; echo 'eval \"$(${local.homebrew_path}/bin/brew shellenv)\"') >> /Users/admin/.zprofile", + "eval \"$($(${local.homebrew_path}/bin/brew --prefix)/bin/brew shellenv)\"" + ] + } + // Ensure Homebrew environment is set up in the shell profile. + provisioner "shell" { + inline = [ + "echo 'Setting up Homebrew environment in shell profile...'", + "echo 'eval \"$(${local.homebrew_path}/bin/brew shellenv)\"' >> /Users/admin/.zshrc", + "echo 'eval \"$(${local.homebrew_path}/bin/brew shellenv)\"' >> /Users/admin/.bash_profile" + ] + } + // Check Homebrew. Ignore errors because we are not using the last version of Xcode. + provisioner "shell" { + inline = [ + "echo 'Checking Homebrew...'", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "${local.homebrew_path}/bin/brew doctor || true" + ] + } + // Create symlink for Homebrew to /usr/local/bin for legacy script compatibility. + provisioner "shell" { + inline = [ + "echo 'Creating Homebrew compatibility symlink...'", + # Check if the path exists and is not already a symlink to avoid errors on reruns + "if [ ! -L /usr/local/bin ]; then sudo ln -s ${local.homebrew_path}/bin /usr/local/bin; fi" + ] + } + // Install dependencies for build and test. + provisioner "shell" { + inline = [ + "echo 'Installing packages using Homebrew...'", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "${local.homebrew_path}/bin/brew install git automake bash libtool cmake python ccache xz pipx orka-vm-tools" + ] + } + + // Install tap2junit using pipx for better isolation. + provisioner "shell" { + environment_vars = ["HOME=/Users/admin", "USER=admin"] + inline = [ + "echo 'Installing tap2junit using pipx...'", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "${local.homebrew_path}/bin/pipx install tap2junit", + // This command automatically adds the pipx path to the user's profile + "${local.homebrew_path}/bin/pipx ensurepath" + ] + } + // Install Java 17 for Jenkins. + provisioner "shell" { + inline = [ + "echo 'Installing JRE...'", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "${local.homebrew_path}/bin/brew install --cask temurin@17", + ] + } + // Print the version of the installed packages. + provisioner "shell" { + inline = [ + "echo 'Printing the version of the installed packages...'", + "eval \"$(${local.homebrew_path}/bin/brew shellenv)\"", + "${local.homebrew_path}/bin/brew list --versions", + "java -version", + // @TODO: Solve the problem with the Xcode version. + //"xcodebuild -version" + ] + } + // Configure ccache to use a shared directory and enable path integration. + provisioner "shell" { + inline = [ + "echo 'Configuring ccache...'", + "mkdir -p /Users/admin/.ccache", + + # Use an HCL heredoc (<<-EOT) to pass a multi-line script to the shell. + # The shell will then execute its own heredoc (cat <<'EOF'). + <<-EOT + cat <<'EOF' > /Users/admin/.ccache/ccache.conf + # This file is managed by Packer. + # Set the cache directory to a shared volume provided by the CI system. + remote_only = true + remote_storage = file:/Volumes/orka/ccache_${var.architecture}|umask=002 + debug = false + debug_dir = /Users/admin/.ccache/debug + debug_level = 2 + EOF + EOT + , # Note the comma here to separate elements in the HCL list + + "chown -R admin:staff /Users/admin/.ccache", + + # Add ccache to the PATH in .zprofile for login shells (which CI uses). + # This makes 'cc' an alias for 'ccache cc', etc. + "echo 'export PATH=\"${local.homebrew_path}/opt/ccache/libexec:$PATH\"' >> /Users/admin/.zprofile" + ] + } + + provisioner "file" { + source = "files/com.mount9p.plist" + destination = "/Users/admin/com.mount9p.plist" + } + + // Set permissions on the shared filesystem launch daemon + provisioner "shell" { + inline = [ + "source /Users/admin/.zprofile", + "if [ $IMAGE_ARCHITECTURE = x64 ]; then", + "sudo mv /Users/admin/com.mount9p.plist /Library/LaunchDaemons/com.mount9p.plist", + "sudo chown root:wheel /Library/LaunchDaemons/com.mount9p.plist", + "sudo chmod 600 /Library/LaunchDaemons/com.mount9p.plist", + "else", + "echo 'Skipping 9p mount setup'", + "fi" + ] + } + + // Fix admin user on intel builds so that they can use the shared ccache. + provisioner "shell" { + script = "files/admin_uid_change.sh" + execute_command = "chmod +x {{ .Path }}; sudo -E /bin/bash -x {{ .Path }}" + } + +} diff --git a/orka/templates/orkaconnect.sh b/orka/templates/orkaconnect.sh new file mode 100644 index 000000000..f4ec5f903 --- /dev/null +++ b/orka/templates/orkaconnect.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Check if a VM name is provided +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +# Construct the SSH command +SSH_COMMAND=$(orka3 vm list -o wide | grep "$1" | awk '{split($7, part, "-");printf "ssh admin@%s -o StrictHostKeyChecking=no -p %s -i ~/.ssh/nodejs_build_%s",$2,$3,part[4]}') + +# Check if the command was successfully generated +if [ -z "$SSH_COMMAND" ]; then + echo "No VM found with name matching '$1'" + exit 1 +fi + +# Execute the SSH command +echo "Executing: $SSH_COMMAND" +eval "$SSH_COMMAND" \ No newline at end of file