diff options
author | Mike Crute <mike@crute.us> | 2017-12-24 03:46:11 +0000 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2017-12-24 03:49:52 +0000 |
commit | 20513b6595ff1ae1bf0be4d899bfc83806b5f5d4 (patch) | |
tree | b81a4ee6effbab11ff37b828b85b89322f1aee19 | |
download | tiny-ec2-bootstrap-release-1.0.0.tar.bz2 tiny-ec2-bootstrap-release-1.0.0.tar.xz tiny-ec2-bootstrap-release-1.0.0.zip |
Initial commitrelease-1.0.0
-rw-r--r-- | LICENSE.txt | 19 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README.md | 56 | ||||
-rw-r--r-- | tiny-ec2-bootstrap | 66 |
4 files changed, 146 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..736d3fe --- /dev/null +++ b/LICENSE.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (c) 2017 Michael Crute | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
4 | this software and associated documentation files (the "Software"), to deal in | ||
5 | the Software without restriction, including without limitation the rights to | ||
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
7 | of the Software, and to permit persons to whom the Software is furnished to do | ||
8 | so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in all | ||
11 | copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
19 | SOFTWARE. | ||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..394004e --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | PREFIX?=/ | ||
2 | |||
3 | .PHONY: install | ||
4 | install: | ||
5 | install -Dm 755 tiny-ec2-bootstrap $(PREFIX)/etc/init.d/tiny-ec2-bootstrap | ||
diff --git a/README.md b/README.md new file mode 100644 index 0000000..86ebfc5 --- /dev/null +++ b/README.md | |||
@@ -0,0 +1,56 @@ | |||
1 | # Tiny EC2 Bootstrapper | ||
2 | |||
3 | This is designed to do the minimal amount of work required to bootstrap an EC2 | ||
4 | instance based on the local settings assigned at boot time as well as the | ||
5 | user's configured settings. This is in-concept similar to | ||
6 | [cloud-init](https://cloudinit.readthedocs.io/en/latest/) but trades features | ||
7 | and cloud platform support for small size and limited external dependencies. | ||
8 | |||
9 | ## Requirements | ||
10 | |||
11 | The most important feature of this bootstrapper is the very limited set of | ||
12 | dependencies. In-fact this works with just busybox provided the wget applet is | ||
13 | built-in. The only required dependencies are: | ||
14 | |||
15 | - bash-like shell (e.g. bash, dash, ash) | ||
16 | - wget | ||
17 | |||
18 | ## Supported Features and Environments | ||
19 | |||
20 | cloud-init has support for many different cloud providers. This project only | ||
21 | supports EC2, specifically the [EC2 metadata | ||
22 | service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) | ||
23 | is a hard requirement of using this bootstrapper. All of the data for the | ||
24 | supported features below is sourced from the EC2 instance metadata service | ||
25 | which runs on every EC2 instance at IP 169.254.169.254. | ||
26 | |||
27 | cloud-init also has a very rich feature set with support for adding users, | ||
28 | installing packages, and many other things. This bootstrap does not support | ||
29 | those things. Instead it supports: | ||
30 | |||
31 | - setting system hostname | ||
32 | - install user's configured SSH keys to the alpine user's authorized_keys file | ||
33 | - run any script-like user data (must start with #!) | ||
34 | |||
35 | These steps only run once. After the initial bootstrap the bootstrapper script | ||
36 | is a no-op. To force the script to run again at boot time remove the file | ||
37 | `/var/lib/cloud/.bootstrap-complete` and reboot the instance. | ||
38 | |||
39 | ## User Data | ||
40 | |||
41 | User data is provided at instance boot time and can be any arbitrary string of | ||
42 | data. The bootstrapper will consider any user data that begins with the ASCII | ||
43 | characters '#!' to be a script. It will write the entire contents of the user | ||
44 | data to `/var/lib/cloud/user-data.sh`, make the file executable, and execute | ||
45 | the file piping any output to `/var/log/cloud-bootstrap.log`. | ||
46 | |||
47 | The user data script can do anything it pleases with the instance. It will be | ||
48 | run as root and networking will be up. No other grantees about system state are | ||
49 | made at the point the script runs. | ||
50 | |||
51 | ## Assumptions | ||
52 | |||
53 | - This was written for Alpine Linux and thus assumes that the login user is | ||
54 | called alpine. This could be configurable in the future but currently is not. | ||
55 | |||
56 | - The script is run by OpenRC | ||
diff --git a/tiny-ec2-bootstrap b/tiny-ec2-bootstrap new file mode 100644 index 0000000..510f4f7 --- /dev/null +++ b/tiny-ec2-bootstrap | |||
@@ -0,0 +1,66 @@ | |||
1 | #!/sbin/openrc-run | ||
2 | # vim:set ft=bash: | ||
3 | |||
4 | description="Provides EC2 cloud bootstrap" | ||
5 | |||
6 | depend() { | ||
7 | need net | ||
8 | provide cloud-final | ||
9 | } | ||
10 | |||
11 | _get_metadata() { | ||
12 | local uri="$1" | ||
13 | wget -qO - "http://169.254.169.254/latest/$uri" 2>/dev/null | ||
14 | } | ||
15 | |||
16 | _update_hostname() { | ||
17 | local ec2_fqdn="$(_get_metadata meta-data/hostname)" | ||
18 | local short_hostname="${ec2_fqdn%%\.*}" | ||
19 | echo "$short_hostname" > /etc/hostname | ||
20 | hostname -F /etc/hostname | ||
21 | echo -e "127.0.1.1\t$ec2_fqdn $short_hostname" >> /etc/hosts | ||
22 | } | ||
23 | |||
24 | _set_ssh_keys() { | ||
25 | local user="$1" | ||
26 | local group="$(getent passwd $user | cut -d: -f4)" | ||
27 | local ssh_dir="$(getent passwd $user | cut -d: -f6)/.ssh" | ||
28 | local keys_file="$ssh_dir/authorized_keys" | ||
29 | |||
30 | if [ ! -d "$ssh_dir" ]; then | ||
31 | mkdir -p "$ssh_dir" | ||
32 | chmod 755 "$ssh_dir" | ||
33 | fi | ||
34 | |||
35 | [ -f "$keys_file" ] && rm "$keys_file" | ||
36 | |||
37 | touch "$keys_file" | ||
38 | chmod 600 "$keys_file" | ||
39 | chown -R $user:$group "$ssh_dir" | ||
40 | |||
41 | for key in "$(_get_metadata meta-data/public-keys/)"; do | ||
42 | echo $(_get_metadata "meta-data/public-keys/${key%=*}/openssh-key/") >> "$keys_file" | ||
43 | done | ||
44 | } | ||
45 | |||
46 | _run_userdata() { | ||
47 | user_data=$(_get_metadata user-data) | ||
48 | if echo $user_data | grep '^#!/' 2>&1 >/dev/null; then | ||
49 | echo "$user_data" > /var/lib/cloud/user-data.sh | ||
50 | chmod +x /var/lib/cloud/user-data.sh | ||
51 | /var/lib/cloud/user-data.sh > /var/log/cloud-bootstrap.log 2>&1 | ||
52 | fi | ||
53 | } | ||
54 | |||
55 | start() { | ||
56 | # Don't bootstrap if the host has already been bootstrapped | ||
57 | [ -f "/var/lib/cloud/.bootstrap-complete" ] && return 0 | ||
58 | |||
59 | [ -d "/var/lib/cloud" ] || mkdir -p /var/lib/cloud | ||
60 | |||
61 | ebegin "Setting ec2 hostname"; _update_hostname; eend $? | ||
62 | ebegin "Setting ec2 user ssh keys"; _set_ssh_keys "alpine"; eend $? | ||
63 | ebegin "Running ec2 user data script"; _run_userdata; eend $? | ||
64 | |||
65 | touch "/var/lib/cloud/.bootstrap-complete" | ||
66 | } | ||