Skip to content

Commit

Permalink
docs: generate documentation using mkdocs material (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
purpleclay authored Aug 28, 2022
1 parent 6220f53 commit dd4b89a
Show file tree
Hide file tree
Showing 16 changed files with 801 additions and 21 deletions.
100 changes: 100 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright (c) 2022 Purple Clay
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# in the Software without restriction, including without limitation the rights
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

name: docs
on:
pull_request:
paths:
- "docs/**"
- "mkdocs.yml"
push:
tags:
- "v*.*.*"
paths:
- "docs/**"
- "mkdocs.yml"
jobs:
build-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Python runtime
uses: actions/setup-python@v4
with:
python-version: 3.x

- name: Set up build cache
uses: actions/cache@v3
id: cache
with:
key: ${{ runner.os }}-${{ hashFiles('.cache/**') }}
path: .cache

- name: Install Python dependencies
run: |
pip install \
"mkdocs-git-committers-plugin-2>=0.4.3" \
"mkdocs-git-revision-date-localized-plugin>=1.0" \
"mkdocs-minify-plugin>=0.3" \
"mkdocs-redirects>=1.0"
- name: Install MkDocs Insiders
if: github.event.repository.fork == false
env:
GH_TOKEN: ${{ secrets.GH_MKDOCS }}
run: |
pip install git+https://${GH_TOKEN}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build
run: mkdocs build
env:
GH_TOKEN: ${{ secrets.GH_MKDOCS }}
GH_GOOGLE_ANALYTICS_KEY: ${{ secrets.GH_GOOGLE_ANALYTICS_KEY }}

- name: HTML Test
uses: wjdp/htmltest-action@master
with:
path: site
config: htmltest.yml

- name: Deploy documentation
if: startsWith(github.ref, 'refs/tags/v')
env:
GH_TOKEN: ${{ secrets.GH_MKDOCS }}
GH_GOOGLE_ANALYTICS_KEY: ${{ secrets.GH_GOOGLE_ANALYTICS_KEY }}
run: |
mkdocs gh-deploy --force
mkdocs --version
- name: Set Custom Domain
if: startsWith(github.ref, 'refs/tags/v')
uses: octokit/[email protected]
id: pages_domain
with:
route: PUT /repos/{owner}/{repo}/pages
owner: purpleclay
repo: imds-mock
cname: imdsmock.purpleclay.dev
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
11 changes: 6 additions & 5 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ dockers:
build_flag_templates:
- "--pull"
- "--label=org.opencontainers.image.licenses=MIT"
- "--label=org.opencontainers.image.description=Mock the Amazon Instance Metadata Service (IMDS) for EC2"
- "--label=org.opencontainers.image.description=Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
Expand All @@ -145,7 +145,7 @@ dockers:
build_flag_templates:
- "--pull"
- "--label=org.opencontainers.image.licenses=MIT"
- "--label=org.opencontainers.image.description=Mock the Amazon Instance Metadata Service (IMDS) for EC2"
- "--label=org.opencontainers.image.description=Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title={{.ProjectName}}"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
Expand Down Expand Up @@ -178,7 +178,7 @@ brews:
name: homebrew-tap
folder: Formula
homepage: "https://github.com/purpleclay/imds-mock"
description: "Mock the Amazon Instance Metadata Service (IMDS) for EC2"
description: "Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)"
license: MIT
install: |
bin.install "imds-mock"
Expand All @@ -201,7 +201,7 @@ nfpms:
- file_name_template: "{{ .ConventionalFileName }}"
id: packages
homepage: "https://github.com/purpleclay/imds-mock"
description: "Mock the Amazon Instance Metadata Service (IMDS) for EC2"
description: "Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)"
maintainer: Purple Clay <[email protected]>
license: MIT
vendor: Purple Clay
Expand Down Expand Up @@ -247,7 +247,7 @@ publishers:

aurs:
- homepage: "https://github.com/purpleclay/imds-mock"
description: "Mock the Amazon Instance Metadata Service (IMDS) for EC2"
description: "Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)"
maintainers:
- "Purple Clay <purple clay at gmail dot com>"
license: MIT
Expand Down Expand Up @@ -277,5 +277,6 @@ release:
## What to do next?
- Read the [documentation](https://purpleclay.github.io/imds-mock/)
- Follow me on [Twitter](https://twitter.com/purpleclaydev)
- Read an article on [Medium](https://medium.com/@purpleclay)
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,29 @@
# imds-mock
Mock the Amazon Instance Metadata Service (IMDS) for EC2
# Instance Metadata Service Mock

[![Build status](https://img.shields.io/github/workflow/status/purpleclay/imds-mock/ci?style=flat-square&logo=go)](https://github.com/purpleclay/imds-mock/actions?workflow=ci)
[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](/LICENSE)
[![Go Report Card](https://goreportcard.com/badge/github.com/purpleclay/imds-mock?style=flat-square)](https://goreportcard.com/report/github.com/purpleclay/imds-mock)
[![Go Version](https://img.shields.io/github/go-mod/go-version/purpleclay/imds-mock.svg?style=flat-square)](go.mod)
[![codecov](https://codecov.io/gh/purpleclay/imds-mock/branch/main/graph/badge.svg)](https://codecov.io/gh/purpleclay/imds-mock)

The Instance Metadata Service (IMDS) stores data about an EC2 that you can use to configure or manage the running of that instance. Data is made accessible through the use of instance categories that adapt to its current state. Designing and developing software around the IMDS service poses two main challenges:

1. First and foremost, an EC2 instance is needed; increasing costs
1. There is no way to influence the IMDS service to simulate EC2 events such as spot termination

Both of which make testing difficult and unattainable.

## So why use a Mock?

The `imds-mock` attempts to solve these problems by providing a tool to accurately simulate any use case within the IMDS service, bringing testing to the forefront without additional cost.

### Features

- All mock responses accurately reflect those from the actual IMDS service
- Customisation of responses is supported through CLI flags
- Support for both IMDSv1 and IMDSv2, with strict IMDSv2 possible
- An in-built eventing system makes the simulation of spot interruption notices both easy and configurable

## Documentation

Check out the latest [documentation](https://purpleclay.github.io/imds-mock/) for a guide on how to use the imds-mock.
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func Execute(out io.Writer) error {

rootCmd := &cobra.Command{
Use: "imds-mock",
Short: "Mocks the Amazon Instance Metadata Service (IMDS) for EC2",
Short: "Easy mocking of the Amazon EC2 Instance Metadata Service (IMDS)",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if spotAction.event != nil {
Expand All @@ -110,7 +110,7 @@ func Execute(out io.Writer) error {
flags.IntVar(&opts.Port, "port", imds.DefaultOptions.Port, "the port to be used at startup")
flags.BoolVar(&opts.Pretty, "pretty", imds.DefaultOptions.Pretty, "if instance categories should return pretty printed JSON")
flags.BoolVar(&opts.Spot, "spot", imds.DefaultOptions.Spot, "enable simulation of a spot instance and interruption notice")
flags.Var(&spotAction, "spot-action", "blah")
flags.Var(&spotAction, "spot-action", "configure the type and delay of the spot interruption notice")

rootCmd.AddCommand(newVersionCmd(out))
rootCmd.AddCommand(newManPagesCmd(out))
Expand Down
42 changes: 42 additions & 0 deletions docs/configure/imdsv2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
icon: material/shield-key-outline
---

# IMDSv2

IMDSv2 uses session-orientated requests, prohibiting access to any endpoints on the imds-mock without using a session token. A client must request a token with a maximum TTL of between one second and six hours before further requests.

It is good security practice to only support IMDSv2[^1] when launching an EC2. Enable the `--imdsv2` flag to simulate this behaviour.

## Enforce Strict IMDSv2

=== "CLI"

```sh
imds-mock --imdsv2
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock --imdsv2
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock --imdsv2
```

## Using a Session Token

1. Request a session token by providing the `X-aws-ec2-metadata-token-ttl-seconds` header with a value between `1` and `21600` seconds (_six hours_):
```sh
TOKEN=`curl -X PUT "http://localhost:1338/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
```
1. Include the token in any subsequent requests by providing the `X-aws-ec2-metadata-token` header:
```sh
curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://localhost:1338/latest/meta-data/
```

[^1]: The AWS Security blog post, [Add defense in depth against open firewalls, reverse proxies, and SSRF vulnerabilities with enhancements to the EC2 Instance Metadata Service](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/), details why using IMDSv2 is important to EC2 security
60 changes: 60 additions & 0 deletions docs/configure/instance-tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
icon: material/tag-outline
status: new
---

# Instance Tags

EC2 instance tags can be exposed through the AWS Instance Metadata Service through the `tags/instance` instance category. The imds-mock exposes a default `Name=imds-mock-ec2` tag to simulate the enablement of this feature.

## Custom Tags

If you wish to override the default instance tags exposed by the imds-mock, the `--instance-tags` flag accepts a list of `key=value` pairs.

=== "CLI"

```sh
imds-mock --instance-tags Name=Test,Environment=Dev
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock --instance-tags Name=Test,Environment=Dev
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock --instance-tags Name=Test,Environment=Dev
```

### Querying a Tag

Any custom tag can be retrieved using the root metadata category `tags/instance`. For example, to retrieve the `Environment` tag:

```sh
curl http://localhost:1338/latest/meta-data/tags/instance/Environment
```

## Excluding Instance Tags

EC2 instance tags are omitted from the AWS Instance Metadata Service by default. Set the `--exclude-instance-tags` flag to simulate this in the imds-mock:

=== "CLI"

```sh
imds-mock --exclude-instance-tags
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock --exclude-instance-tags
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock --exclude-instance-tags
```
27 changes: 27 additions & 0 deletions docs/configure/on-demand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
icon: material/rocket-launch-outline
---

# On-Demand Instance

The imds-mock simulates an on-demand instance by default. Once the mock has started, all supported instance categories[^1] will be available for querying via both IMDSv1 and IMDSv2.

=== "CLI"

```sh
imds-mock
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock
```

[^1]: A list of currently supported instance categories can be found [here](../reference/instance-metadata.md)
56 changes: 56 additions & 0 deletions docs/configure/spot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
icon: material/timer-cog-outline
status: new
---

# Spot Instance

The imds-mock can simulate a spot instance. A spot instance is more cost-effective than an on-demand instance but is at the mercy of spot interruptions. An interruption notice will typically be issued by Amazon EC2 two minutes before it stops or terminates your spot instance, with no warning issued before hibernation.

## Switching Instance Type

Set the `--spot` flag to enable spot simulation within the imds-mock. The `spot/instance-action` metadata category will immediately be available and will return an interruption notice to terminate the instance.

=== "CLI"

```sh
imds-mock --spot
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock --spot
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock --spot
```

## Configure Interruption Notice

You have complete control over the spot interruption notice raised by the imds-mock. Set the `--spot-action` flag, specifying the interruption type (`terminate`, `stop` or `hibernate`) and an initial delay to raise a spot interruption notice.

=== "CLI"

```sh
imds-mock --spot --spot-action stop=10s
```

=== "DockerHub"

```sh
docker run -p 1338:1338 purpleclay/imds-mock --spot --spot-action stop=10s
```

=== "GHCR"

```sh
docker run -p 1338:1338 ghcr.io/purpleclay/imds-mock --spot --spot-action stop=10s
```

!!! info "Handling hibernation a little differently"

A hibernate interruption notice does not provide a two-minute warning and is effective immediately. It, therefore, should not be accessible through the `spot/instance-action` metadata category. However, as the mock will remain running, this category will be available and contain details of the hibernation interruption.
Loading

0 comments on commit dd4b89a

Please sign in to comment.