From 00d6b4ef58864899101f3b4ce4a2dd3f08f66df4 Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Wed, 2 Sep 2020 13:13:21 +0100 Subject: [PATCH 1/7] Make a macOS user capable of being the service's user-account --- CHANGELOG.md | 6 +- README.md | 2 +- defaults/main.yml | 2 +- files/create-local-user.Darwin.sh | 138 ++++++++++++++++++++++++++++++ tasks/install-on-Darwin.yml | 19 ++++ tasks/install-on-Windows.yml | 2 +- 6 files changed, 165 insertions(+), 4 deletions(-) create mode 100755 files/create-local-user.Darwin.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index e226e41..dde0775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -... +- Added: macOS installation now creates a user to run the service as, optionally as an administrator. + +## 3.1.1 - 2020-07-31 + +- Fixed: systemd path to buildkite agent logs; needs to be a file, not a directory. ## 3.1.0 - 2020-02-26 diff --git a/README.md b/README.md index bf6c57b..54627c8 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Variable names below map to [the agent configuration documentation](https://buil - `buildkite_agent_bootstrap_script` - `buildkite_agent_git_clean_flags` - `buildkite_agent_git_clone_flags` +- `buildkite_agent_grant_admin` - If `true` make the `buildkite_agent_username` user be a member of the local `Administrators` group. You must assess your own security risk tradeoff with the necessity for build tools needing privileges. - `buildkite_agent_no_color` - `buildkite_agent_no_command_eval` - `buildkite_agent_no_plugins` @@ -62,7 +63,6 @@ Variable names below map to [the agent configuration documentation](https://buil - `buildkite_agent_nssm_exe` - the full path to nssm.exe in case it's not on `PATH`. - `buildkite_agent_nssm_version` - Which version of [NSSM] to use to manage the buildkite-agent process as a service. -- `buildkite_agent_windows_grant_admin` - If `True` make the `buildkite_agent_username` user be a member of the local `Administrators` group. You must assess your own security risk tradeoff with the necessity for Windows build tools needing privileges. #### Darwin diff --git a/defaults/main.yml b/defaults/main.yml index b78120b..f6f2938 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -87,7 +87,7 @@ buildkite_agent_systemd_override_template: buildkite-agent.override.conf.j2 buildkite_agent_nssm_exe: "C:/ProgramData/chocolatey/bin/nssm.exe" buildkite_agent_nssm_version: "2.24.101.20180116" buildkite_agent_platform: "amd64" -buildkite_agent_windows_grant_admin: False +buildkite_agent_grant_admin: False # Darwin options buildkite_agent_load_bash_profile: yes diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh new file mode 100755 index 0000000..e0c5331 --- /dev/null +++ b/files/create-local-user.Darwin.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +set -o errexit -o pipefail -o nounset +[[ -n "${SCRIPT_DEBUG:-}" ]] && set -o xtrace + +function log() { + echo "${@}" >&2 +} + +function die() { + log "${@}" + exit 1 +} + +function array_contains() { + if [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]]; then + return 0 + fi + return 1 +} + +function has_user() { + local user_name="${1?:"1st arg must be user name"}" + log "has_user: ${user_name}" + if /usr/bin/dscl . -list /Users | grep "^${user_name}$"; then + log "Exists" + return 0 + fi + log "Does not exist" + return 1 +} + +function random_string() { + LC_CTYPE=C tr -dc 'a-zA-Z0-9' <"/dev/urandom" | + head -c 32 || log "random_string exit'd $?" +} + +function find_new_user_id() { + local highest_id + highest_id="$(/usr/bin/dscl . -list /Users UniqueID | awk '{print $2}' | sort -ug | tail -n 1 | bc)" + + echo $(( highest_id + 1 )) +} + +function user_home_dir() { + local user_name="${1?:"1st arg must be user's username"}" + + echo "/Users/${user_name}" +} + +function create_user() { + local user_name="${1?:"1st arg must be user's username"}" + log "Creating ${user_name} ..." + + local user_pass + user_pass="$(random_string)" + + local home_dir + home_dir="$(user_home_dir "${user_name}")" + + if [[ -d "${home_dir}" ]]; then + echo "Error: ${home_dir} folder exists already." + return 1 + fi + + log "Finding new user ID..." + local user_uid + user_uid="$(find_new_user_id "${user_name}")" + log "Using user ID ${user_uid} ." + + /usr/bin/dscl "." -create "/Users/${user_name}" + /usr/bin/dscl "." -create "/Users/${user_name}" RealName "${user_name}" + /usr/bin/dscl "." -create "/Users/${user_name}" UserShell "/bin/bash" + /usr/bin/dscl "." -create "/Users/${user_name}" UniqueID "${user_uid}" + /usr/bin/dscl "." -create "/Users/${user_name}" PrimaryGroupID "20" # '20' == 'staff' + /usr/bin/dscl "." -create "/Users/${user_name}" NFSHomeDirectory "${home_dir}" + + /usr/bin/dscl "." -passwd "/Users/${user_name}" "${user_pass}" + + # https://superuser.com/questions/20420/what-is-the-difference-between-the-default-groups-on-mac-os-x + /usr/bin/dscl "." -append /Groups/staff GroupMembership "${user_name}" + if [[ "${want_admin}" == "true" ]]; then + log "Making ${user_name} an admin..." + /usr/bin/dscl "." -append /Groups/admin GroupMembership "${user_name}" + fi + + # create home directory + /bin/cp -R "/System/Library/User Template/English.lproj" "${home_dir}" + /usr/sbin/chown -R "${user_name}:staff" "${home_dir}" +} + +function write_user_defaults() { + local user_name="${1?:"1st arg must be user's username"}" + log "Writing user defaults for ${user_name} ..." + + local home_dir + home_dir="$(user_home_dir "${user_name}")" + + # disable Apple ID, iCloud, Siri, etc + local PRODUCT_VERSION + PRODUCT_VERSION="$(sw_vers -productVersion)" + local PRODUCT_BUILD + PRODUCT_BUILD="$(/usr/bin/sw_vers -buildVersion)" + local SETUP_ASSISTANT + SETUP_ASSISTANT="${home_dir}/Library/Preferences/com.apple.SetupAssistant" + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeApplePaySetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeAvatarSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeCloudDiagnostics -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeCloudSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeSiriSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeSyncSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" GestureMovieSeen none + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeSyncSetup2 -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeTouchIDSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeiCloudLoginForStorageServices -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" LastSeenCloudProductVersion "${PRODUCT_VERSION}" + /usr/bin/defaults write "${SETUP_ASSISTANT}" LastSeenBuddyBuildVersion "${PRODUCT_BUILD}" + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeePrivacy -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeSiriSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeAppearanceSetup -bool TRUE + /usr/bin/defaults write "${SETUP_ASSISTANT}" DidSeeTrueTonePrivacy -bool TRUE + + /usr/sbin/chown "${user_name}" "${SETUP_ASSISTANT}.plist" +} + +user_name="${1?:"1st arg must be user's name"}" +want_admin="${2:-"false"}" + +if has_user "${user_name}"; then + die "Exiting: User exists ${user_name}." +fi + +home_dir="$(user_home_dir "${user_name}")" +if [[ -d "${home_dir}" ]]; then + die "Exiting: Home directory ${home_dir} already existed." +fi + +create_user "${user_name}" "${want_admin}" +write_user_defaults "${user_name}" diff --git a/tasks/install-on-Darwin.yml b/tasks/install-on-Darwin.yml index ddc1331..593d677 100644 --- a/tasks/install-on-Darwin.yml +++ b/tasks/install-on-Darwin.yml @@ -13,6 +13,25 @@ state: latest update_homebrew: yes +- name: Create user + block: + - name: temp script + tempfile: + state: file + register: create_user_temp_file + + - name: Write script to make user + copy: + src: create-local-user.{{ ansible_os_family }}.sh + dest: "{{ create_user_temp_file.path }}/create-local-user.sh" + mode: 0755 + + - name: Create user via script + shell: >- + {{ create_user_temp_file.path }}/create-local-user.sh + '{{ agent_username }}' + '{{ buildkite_agent_grant_admin | ternary("true", "false") }}' + - name: Configure Buildkite template: src: "buildkite-agent.cfg.j2" diff --git a/tasks/install-on-Windows.yml b/tasks/install-on-Windows.yml index ff0f9b0..9b88a5f 100644 --- a/tasks/install-on-Windows.yml +++ b/tasks/install-on-Windows.yml @@ -33,7 +33,7 @@ name: Administrators members: - "{{ buildkite_agent_username }}" - state: "{{ 'present' if buildkite_agent_windows_grant_admin else 'absent' }}" + state: "{{ 'present' if buildkite_agent_grant_admin else 'absent' }}" notify: - restart-windows-buildkite From d241179518e96c13f2e21b4fd29cc04efe9e367c Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Wed, 2 Sep 2020 13:24:12 +0100 Subject: [PATCH 2/7] Generate password via ansible lookup, supply via env var --- files/create-local-user.Darwin.sh | 2 +- tasks/install-on-Darwin.yml | 15 ++++++++++++--- tasks/install-on-Windows.yml | 6 +++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh index e0c5331..c23785c 100755 --- a/files/create-local-user.Darwin.sh +++ b/files/create-local-user.Darwin.sh @@ -52,7 +52,7 @@ function create_user() { log "Creating ${user_name} ..." local user_pass - user_pass="$(random_string)" + user_pass="${USER_PASSWORD:-"$(random_string)"}" local home_dir home_dir="$(user_home_dir "${user_name}")" diff --git a/tasks/install-on-Darwin.yml b/tasks/install-on-Darwin.yml index 593d677..d040953 100644 --- a/tasks/install-on-Darwin.yml +++ b/tasks/install-on-Darwin.yml @@ -15,22 +15,31 @@ - name: Create user block: + - name: make password for user + set_fact: + buildkite_agent_user_password: "{{ lookup('password', '/tmp/bk-agent-password length=32 chars=ascii_letters,digits,punctuation') }}" + no_log: "{{ buildkite_agent_hide_secrets | default(true) }}" + - name: temp script tempfile: state: file - register: create_user_temp_file + register: buildkite_agent_create_user_temp_file - name: Write script to make user copy: src: create-local-user.{{ ansible_os_family }}.sh - dest: "{{ create_user_temp_file.path }}/create-local-user.sh" + dest: "{{ buildkite_agent_create_user_temp_file.path }}/create-local-user.sh" mode: 0755 - name: Create user via script shell: >- - {{ create_user_temp_file.path }}/create-local-user.sh + {{ buildkite_agent_create_user_temp_file.path }}/create-local-user.sh '{{ agent_username }}' '{{ buildkite_agent_grant_admin | ternary("true", "false") }}' + args: + creates: "/Users/{{ agent_username }}" + environment: + USER_PASSWORD: "{{ buildkite_agent_user_password }}" - name: Configure Buildkite template: diff --git a/tasks/install-on-Windows.yml b/tasks/install-on-Windows.yml index 9b88a5f..71299a7 100644 --- a/tasks/install-on-Windows.yml +++ b/tasks/install-on-Windows.yml @@ -1,7 +1,7 @@ --- - name: make password for user set_fact: - user_password: "{{ lookup('password', '/tmp/bk-agent-password length=32 chars=ascii_letters,digits,punctuation') }}" + buildkite_agent_user_password: "{{ lookup('password', '/tmp/bk-agent-password length=32 chars=ascii_letters,digits,punctuation') }}" no_log: "{{ buildkite_agent_hide_secrets | default(true) }}" - name: make the user @@ -9,7 +9,7 @@ description: "{{ buildkite_agent_user_description }}" name: "{{ buildkite_agent_username }}" # TODO: Single static file with no isolation between runs is unsafe (but that's unlikely to occur) - password: "{{ user_password }}" + password: "{{ buildkite_agent_user_password }}" password_never_expires: yes user_cannot_change_password: yes register: buildkite_agent_user @@ -109,5 +109,5 @@ win_service: name: buildkite-agent username: "{{ buildkite_agent_username }}" - password: "{{ user_password }}" + password: "{{ buildkite_agent_user_password }}" state: "{{ 'started' if buildkite_agent_allow_service_startup[ansible_os_family] else 'stopped' }}" From 244e89dfa3f7a4a61c576ffe948fa6c9720a63d5 Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Wed, 2 Sep 2020 13:38:22 +0100 Subject: [PATCH 3/7] reformat for codacy linting --- CHANGELOG.md | 72 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dde0775..7a146b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -- Added: macOS installation now creates a user to run the service as, optionally as an administrator. +* Added: macOS installation now creates a user to run the service as, optionally as an administrator. -## 3.1.1 - 2020-07-31 +## 3.1.1: 2020-07-31 -- Fixed: systemd path to buildkite agent logs; needs to be a file, not a directory. +* Fixed: systemd path to buildkite agent logs; needs to be a file, not a directory. -## 3.1.0 - 2020-02-26 +## 3.1.0: 2020-02-26 Add support for shims/scripts wrapping the `buildkite-agent` binary, instead of directly calling the binary. This can be useful, for example, if you need to fetch your agent registration token from a secret store before running `buildkite-agent`. @@ -22,66 +22,66 @@ If not using a shim/script, no changes are needed. To use a shim instead of directly calling the `buildkite-agent` binary, point `buildkite_agent_executable` to your shim, and `buildkite_agent_start_command` to your shim's args. -- Added `buildkite_agent_executable` option. -- Added `buildkite_agent_start_command` option. +* Added `buildkite_agent_executable` option. +* Added `buildkite_agent_start_command` option. -## 3.0.0 - 2019-11-13 +## 3.0.0: 2019-11-13 Version bump for breaking change. This is the same as 2.2.1 with corrected meta/main.yml. -## 2.2.1 - 2019-11-12 +## 2.2.1: 2019-11-12 -- fixes to ansible 2.9.0 updates. +* fixes to ansible 2.9.0 updates. -## 2.2.0 - 2019-11-07 +## 2.2.0: 2019-11-07 -- porting to support ansible 2.9.0. +* porting to support ansible 2.9.0. -## 2.1.0 - 2019-08-20 +## 2.1.0: 2019-08-20 -- `buildkite_agent_username` option for configuring the name of the user to run the service as. -- `buildkite_agent_user_description` option for configuring the description of the user to run the service as. +* `buildkite_agent_username` option for configuring the name of the user to run the service as. +* `buildkite_agent_user_description` option for configuring the description of the user to run the service as. -## 2.0.0 - 2019-08-11 +## 2.0.0: 2019-08-11 -- require ansible `2.8.x` for `win_user_profile` support. -- take care of `win_nssm` deprecations within ansible 2.8.x. +* require ansible `2.8.x` for `win_user_profile` support. +* take care of `win_nssm` deprecations within ansible 2.8.x. -## 1.2.1 - 2019-04-25 +## 1.2.1: 2019-04-25 -- `buildkite_agent_nssm_exe` option. -- `buildkite_agent_tags_including_queue` option. +* `buildkite_agent_nssm_exe` option. +* `buildkite_agent_tags_including_queue` option. -## 1.2.0 - 2019-03-16 +## 1.2.0: 2019-03-16 ### Added -- `buildkite_agent_allow_service_startup` option. -- `buildkite_agent_expose_secrets` option. -- `buildkite_agent_tags_from_gcp_labels` option. -- `buildkite_agent_start_parameters` option for Debian and Windows. -- Debian `buildkite_agent_systemd_override_template` option. - - Related - stop using systemd _template_ unit file (because `buildkite_agent_start_parameters` and v3.6.0+ allow `--spawn` for multiple job-runners). +* `buildkite_agent_allow_service_startup` option. +* `buildkite_agent_expose_secrets` option. +* `buildkite_agent_tags_from_gcp_labels` option. +* `buildkite_agent_start_parameters` option for Debian and Windows. +* Debian `buildkite_agent_systemd_override_template` option. + * Related - stop using systemd _template_ unit file (because `buildkite_agent_start_parameters` and v3.6.0+ allow `--spawn` for multiple job-runners). -## 1.1.0 - 2018-12-11 +## 1.1.0: 2018-12-11 ### Added -- macOS support - #7 -- Windows support - #6 +* macOS support - #7 +* Windows support - #6 -## 1.0.0 - 2018-04-18 +## 1.0.0: 2018-04-18 ### Added -- Support for Buildkite Agent v3. -- Support for Ubuntu 16.04. +* Support for Buildkite Agent v3. +* Support for Ubuntu 16.04. ### Removed -- Remove support for Ubuntu 14.04. -- Remove support for Buildkite Agent v2. +* Remove support for Ubuntu 14.04. +* Remove support for Buildkite Agent v2. ## 0.1.0 -- Initial release. +* Initial release. From e3d71f2915741c84f9939ad0cb653d388132b00b Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Thu, 3 Sep 2020 00:10:57 +0100 Subject: [PATCH 4/7] fixes, autologin --- files/create-local-user.Darwin.sh | 29 +++++++++++++++++++---- files/kcpassword | 39 +++++++++++++++++++++++++++++++ tasks/install-on-Darwin.yml | 16 ++++++------- 3 files changed, 70 insertions(+), 14 deletions(-) create mode 100755 files/kcpassword diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh index c23785c..1b16db7 100755 --- a/files/create-local-user.Darwin.sh +++ b/files/create-local-user.Darwin.sh @@ -49,11 +49,9 @@ function user_home_dir() { function create_user() { local user_name="${1?:"1st arg must be user's username"}" + local user_pass="${2?:"2nd arg must be user's password"}" log "Creating ${user_name} ..." - local user_pass - user_pass="${USER_PASSWORD:-"$(random_string)"}" - local home_dir home_dir="$(user_home_dir "${user_name}")" @@ -122,8 +120,24 @@ function write_user_defaults() { /usr/sbin/chown "${user_name}" "${SETUP_ASSISTANT}.plist" } +function configure_auto_login() { + local user_name="${1?:"1st arg must be user's username"}" + local user_pass="${2?:"2nd arg must be user's password"}" + + log "Setting up automatic login for ${user_name} ..." + + local kc_password_path + kc_password_path="$(dirname "${BASH_SOURCE[0]}")/kcpassword" + "${kc_password_path}" "${user_pass}" + /bin/chmod 600 "/private/etc/kcpassword" + /usr/bin/defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser "${user_name}" + /bin/chmod 644 "/Library/Preferences/com.apple.loginwindow.plist" +} + user_name="${1?:"1st arg must be user's name"}" -want_admin="${2:-"false"}" +user_type="${2:-"standard"}" +auto_login="${3:-"true"}" +user_pass="${USER_PASSWORD:-"$(random_string)"}" if has_user "${user_name}"; then die "Exiting: User exists ${user_name}." @@ -134,5 +148,10 @@ if [[ -d "${home_dir}" ]]; then die "Exiting: Home directory ${home_dir} already existed." fi -create_user "${user_name}" "${want_admin}" +create_user "${user_name}" "${user_pass}" "${user_type}" write_user_defaults "${user_name}" +if [[ "${auto_login}" == "true" ]]; then + configure_auto_login "${user_name}" "${user_pass}" +else + log "Skip: auto_login was ${auto_login}. If you want the user to be automatically logged in, choose 'true'." +fi diff --git a/files/kcpassword b/files/kcpassword new file mode 100755 index 0000000..2f77699 --- /dev/null +++ b/files/kcpassword @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +# https://github.com/xfreebird/kcpassword/blob/master/kcpassword + +# Port of Gavin Brock's Perl kcpassword generator to Python, by Tom Taylor +# . +# Perl version: http://www.brock-family.org/gavin/perl/kcpassword.html +# https://github.com/timsutton/osx-vm-templates/blob/master/scripts/support/set_kcpassword.py + +import sys +import os + +def kcpassword(passwd): + # The magic 11 bytes - these are just repeated + # 0x7D 0x89 0x52 0x23 0xD2 0xBC 0xDD 0xEA 0xA3 0xB9 0x1F + key = [125,137,82,35,210,188,221,234,163,185,31] + key_len = len(key) + + passwd = [ord(x) for x in list(passwd)] + # pad passwd length out to an even multiple of key length + r = len(passwd) % key_len + if (r > 0): + passwd = passwd + [0] * (key_len - r) + + for n in range(0, len(passwd), len(key)): + ki = 0 + for j in range(n, min(n+len(key), len(passwd))): + passwd[j] = passwd[j] ^ key[ki] + ki += 1 + + passwd = [chr(x) for x in passwd] + return "".join(passwd) + +if __name__ == "__main__": + passwd = kcpassword(sys.argv[1]) + fd = os.open('/etc/kcpassword', os.O_WRONLY | os.O_CREAT, 0o600) + file = os.fdopen(fd, 'w') + file.write(passwd) + file.close() diff --git a/tasks/install-on-Darwin.yml b/tasks/install-on-Darwin.yml index d040953..a8a5c90 100644 --- a/tasks/install-on-Darwin.yml +++ b/tasks/install-on-Darwin.yml @@ -20,20 +20,18 @@ buildkite_agent_user_password: "{{ lookup('password', '/tmp/bk-agent-password length=32 chars=ascii_letters,digits,punctuation') }}" no_log: "{{ buildkite_agent_hide_secrets | default(true) }}" - - name: temp script - tempfile: - state: file - register: buildkite_agent_create_user_temp_file - - - name: Write script to make user + - name: Write scripts needed to make user copy: - src: create-local-user.{{ ansible_os_family }}.sh - dest: "{{ buildkite_agent_create_user_temp_file.path }}/create-local-user.sh" + src: "{{ item }}" + dest: "/usr/local/bin/{{ item }}" mode: 0755 + with_items: + - "create-local-user.{{ ansible_os_family }}.sh" + - "kcpassword" - name: Create user via script shell: >- - {{ buildkite_agent_create_user_temp_file.path }}/create-local-user.sh + /usr/local/bin/create-local-user.{{ ansible_os_family }}.sh '{{ agent_username }}' '{{ buildkite_agent_grant_admin | ternary("true", "false") }}' args: From c447f065d8ec915f8950a430ca5fe5313a327c63 Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Thu, 3 Sep 2020 10:22:53 +0100 Subject: [PATCH 5/7] error trap + become --- files/create-local-user.Darwin.sh | 28 ++++++++++++++++++++++++++++ tasks/install-on-Darwin.yml | 1 + 2 files changed, 29 insertions(+) diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh index 1b16db7..9325603 100755 --- a/files/create-local-user.Darwin.sh +++ b/files/create-local-user.Darwin.sh @@ -11,6 +11,34 @@ function die() { exit 1 } +# Print traceback of call stack, starting from the call location. +# An optional argument can specify how many additional stack frames to skip. +print_traceback() { + local skip=${1:-0} + local start=$((skip + 1)) + local end=${#BASH_SOURCE[@]} + local curr=0 + log "Traceback (most recent call first):" + for ((curr = start; curr < end; curr++)); do + local prev=$((curr - 1)) + local func="${FUNCNAME[$curr]}" + local file="${BASH_SOURCE[$curr]}" + local line="${BASH_LINENO[$prev]}" + log " at ${file}:${line} in ${func}()" + done +} + +_err_trap() { + local err=$? + local cmd="${BASH_COMMAND:-}" + # Disable echoing all commands as this makes the traceback really hard to follow + set +x + log "panic: uncaught error" + print_traceback 1 + log "${cmd} exited ${err}" +} +trap _err_trap ERR + function array_contains() { if [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]]; then return 0 diff --git a/tasks/install-on-Darwin.yml b/tasks/install-on-Darwin.yml index a8a5c90..4eb03dd 100644 --- a/tasks/install-on-Darwin.yml +++ b/tasks/install-on-Darwin.yml @@ -36,6 +36,7 @@ '{{ buildkite_agent_grant_admin | ternary("true", "false") }}' args: creates: "/Users/{{ agent_username }}" + become: true environment: USER_PASSWORD: "{{ buildkite_agent_user_password }}" From 9171437ee4883bef7cf28b6543a531aa0b45d4bc Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Thu, 3 Sep 2020 10:35:17 +0100 Subject: [PATCH 6/7] fix var --- files/create-local-user.Darwin.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh index 9325603..32278fb 100755 --- a/files/create-local-user.Darwin.sh +++ b/files/create-local-user.Darwin.sh @@ -78,6 +78,7 @@ function user_home_dir() { function create_user() { local user_name="${1?:"1st arg must be user's username"}" local user_pass="${2?:"2nd arg must be user's password"}" + local user_type="${3?:"3rd arg must be user's type [standard, admin]"}" log "Creating ${user_name} ..." local home_dir @@ -104,7 +105,7 @@ function create_user() { # https://superuser.com/questions/20420/what-is-the-difference-between-the-default-groups-on-mac-os-x /usr/bin/dscl "." -append /Groups/staff GroupMembership "${user_name}" - if [[ "${want_admin}" == "true" ]]; then + if [[ "${user_type}" == "admin" ]]; then log "Making ${user_name} an admin..." /usr/bin/dscl "." -append /Groups/admin GroupMembership "${user_name}" fi From 7e926ba95cc0476b83c714cfd5d3237334aa8b83 Mon Sep 17 00:00:00 2001 From: Peter Mounce Date: Thu, 3 Sep 2020 15:34:40 +0100 Subject: [PATCH 7/7] Practically anything meaningful to do with CI requires XCode, so add user into _developers --- files/create-local-user.Darwin.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/create-local-user.Darwin.sh b/files/create-local-user.Darwin.sh index 32278fb..750ff83 100755 --- a/files/create-local-user.Darwin.sh +++ b/files/create-local-user.Darwin.sh @@ -105,6 +105,8 @@ function create_user() { # https://superuser.com/questions/20420/what-is-the-difference-between-the-default-groups-on-mac-os-x /usr/bin/dscl "." -append /Groups/staff GroupMembership "${user_name}" + # https://stackoverflow.com/questions/1837889/authorize-a-non-admin-developer-in-xcode-mac-os + /usr/bin/dscl "." -append /Groups/_developer GroupMembership "${user_name}" if [[ "${user_type}" == "admin" ]]; then log "Making ${user_name} an admin..." /usr/bin/dscl "." -append /Groups/admin GroupMembership "${user_name}"