aws / ec2-macos-init

EC2 macOS Init is the launch daemon used to initialize Mac instances within EC2.
https://aws.amazon.com/ec2/instance-types/mac/
Apache License 2.0
148 stars 19 forks source link
aws cloud-computing ec2 macos

EC2 macOS Init

Overview

EC2 macOS Init is the launch daemon used to initialize Mac instances within EC2. It runs many tasks quickly and in parallel through the use of Priority Groups. Priority Groups are logical groupings of tasks which can be run at the same time without impacting each other. EC2 macOS Init will wait for all modules in a priority group to complete before moving on to the next group.

Important files for EC2 macOS Init are located in the following locations:

Usage

Most of the time, no interaction with EC2 macOS Init will be needed. It is automatically run on every boot by launchd using the included com.amazon.ec2.macos-init.plist file. However, it can also be used interactively with the following options:

Run

sudo ec2-macos-init run

The run flag runs EC2 macOS Init using the current configuration located at /usr/local/aws/ec2-macos-init/init.toml. If EC2 macOS Init has been previously run on the current instance, the instance history will be read and the current run will be treated as a second boot (things may be skipped depending on their run type).

Clean

sudo ec2-macos-init clean (-all)

The clean flag removes instance history located in the /usr/local/aws/ec2-macos-init/instances/ directory. With no arguments, it will only remove any history matching the current instance ID. If provided -all, it will remove all instance history. This easily allows EC2 macOS Init to be re-run as though it were the first boot, something which is recommended as a part of the process to generate a custom AMI from a currently running instance resulting in a clean history for the new AMI.

Version

sudo ec2-macos-init version

The version flag returns the current version of EC2 macOS init as well as the date of the commit used to build the executable.

Init.toml Configuration Options

EC2 macOS Init uses a single TOML file to configure boot options. These are divided into modules which can be added to any launch group and run in any order. Current modules and options include:

Common Options

The following options are available for all modules:

Additionally, all module configurations must contain exactly one of the following, set to true:

Command

The Command module runs a single command. This can be used for a wide variety of tasks on launch. It should be noted that any shell redirection will not work as anticipated as this is intended only for simple commands. In more complex cases, it's suggested to use this module to execute a shell script containing the required commands.

Example

[[Module]]
  Name = "Important-Init-Command"
  PriorityGroup = 4 # Fourth group
  RunOnce = true # Run once, ever
  FatalOnError = true # Stop running Init if there is an error 
  [Module.Command]
    Cmd = ["touch", "/tmp/file.txt"] # A simple command
    RunAsUser = "ec2-user" # Run as ec2-user
    EnvironmentVars = ["MY_KEY=myValue"] # One environment variable named MY_KEY

Network Check

The NetworkCheck module gets the default gateway and pings it to check if the network is up. This is useful as a way to gate subsequent modules which require network access (internet or IMDS).

Example

[[Module]]
  Name = "Network-Check"
  PriorityGroup = 1 # First group
  RunPerBoot = true # Run every boot
  FatalOnError = true # Fatal if there's an error - this must succeed
  [Module.NetworkCheck]
    PingCount = 6 # Six attempts

SSH Keys

The SSHKeys module manages the .ssh/authorized_keys file on boot. There are many options here, but it is primarily used to pull OpenSSH keys from IMDS on first launch.

Example

[[Module]]
  Name = "Get-SSH-Keys"
  PriorityGroup = 3 # Third group
  FatalOnError = true # Exit on failure - this is required to log in
  RunPerInstance = true # Run only once per instance
  [Module.SSHKeys]
    GetIMDSOpenSSHKey = true # Get the key from IMDS
    User = "ec2-user" # Apply the key to ec2-user
    DedupKeys = true # Remove duplicate keys
    OverwriteAuthorizedKeys = false # Append to authorized_keys to avoid erasing any additional keys on future instances

Userdata

The UserData module pulls User Data from IMDS and provides the option to execute it. This is stored in a file at /usr/local/aws/ec2-macos-init/instances/<instance-id>/userdata. This can be useful for non-executables (like JSON) as well, by pulling the data from IMDS and making it immediately available without having to retrieve it directly.

Example

[[Module]]
  Name = "Execute-User-Data"
  PriorityGroup = 4 # Fourth group
  RunPerInstance = true # Run once per instance
  FatalOnError = false # Best effort, don't fatal on error
  [Module.UserData]
    ExecuteUserData = true # Execute the userdata

System Configuration

The SystemConfig module provides a few interfaces for setting system configuration parameters, primarily through the use of sysctl and defaults.

Example

[[Module]]
  Name = "System-Configuration"
  PriorityGroup = 2 # Second group
  RunPerBoot = true # Run every boot to enforce these parameters
  FatalOnError = false # Best effort, don't fatal on error
  [Module.SystemConfig]
    secureSSHDConfig = true # secure sshd_config on OS update
    [[Module.SystemConfig.Sysctl]]
      value = "my.favorite.parameter=42" # use sysctl to set my.favorite.parameter
    [[Module.SystemConfig.Defaults]]
      plist = "/Library/Preferences/com.amazon.ec2.plist" # use defaults to set a parameter in this plist
      parameter = "PlistParameter"
      type = "bool"
      value = "false"

User Management

The UserManagement module provides the ability to safely randomize an existing user's password.

Example

[[Module]]
  Name = "ManageEC2User"
  PriorityGroup = 2 # Second group
  RunOnce = true # Run only on the first boot
  FatalOnError = true # Must succeed
  [Module.UserManagement]
    User = "ec2-user" # This user must exist locally in /Users/
    RandomizePassword = true # default is true

Building

The build.sh script has been provided for easy builds. This script sets build-time variables, gets dependencies, and then builds the binary for darwin/amd64. Once complete, the binary, launchd plist, and init.toml configuration file need to be copied to the locations described in the Overview section of this README before testing.

Contributing

Please feel free to submit issues, fork the repository and send pull requests! See CONTRIBUTING for more information.

Security

See the Security section of CONTRIBUTING for more information.

License

This project is licensed under the Apache-2.0 License.