Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial work to do reliable backup of SSM parameters #1

Open
wants to merge 14 commits into
base: reviewed
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
*.retry
*~
*venv
aws_credentials*
*password*
\#*
*environment
*postfix
.#*
*.dat
*.pub
gpgtemp
keys/
build
*.log
dump.sql*
*.pri
mockstmp
.anslk_*
.prepare*
test-config*
__pycache__
.mypy_cache
*.gpg
bin/backup_encrypt
*.pyc
dist
MANIFEST
deploy_key
deploy_key.bck
encrypted_build_files
encrypted_build_files.tjz
*.egg-info
*.makestamp
.hypothesis
30 changes: 30 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
exclude: '^$'
fail_fast: false
repos:
- repo: https://github.com/ambv/black
rev: stable
hooks:
- id: black
language_version: python3.7
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v1.2.3
hooks:
- id: check-added-large-files
- id: check-json
- id: detect-private-key
- id: end-of-file-fixer
- id: flake8
exclude: '^features/.*_steps/*'
args:
- --ignore=W503,E402,E501
- --max-line-length=131
- id: forbid-new-submodules
- id: check-yaml
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'master' # Use the sha / tag you want to point at
hooks:
- id: mypy
# - repo: https://github.com/Lucas-C/pre-commit-hooks-go
# sha: v1.0.0
# hooks:
# - id: checkmake
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
AWS_ACCOUNT_NAME ?= michael

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove all AWS defaults ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's there as a reminder to set up credentials which make it difficult to accidentally do things on production. Will become clear when I add CI.

AWS_DEFAULT_REGION ?= eu-west-1
PYTHON ?= python3
BEHAVE ?= behave

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem to be used anywhere.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as above - will commit to clear this up soon

KEYFILE ?=.anslk_random_testkey
michael-paddle marked this conversation as resolved.
Show resolved Hide resolved

LIBFILES := $(shell find backup_cloud_ssm -name '*.py')

all: lint test

# pytest-mocked is much faster than non-mocked which is slower even than
# the functional tests so run it first, then behave then ffinally the
michael-paddle marked this conversation as resolved.
Show resolved Hide resolved
# full pytest tests so that failures are detected early where possible.
test: develop pytest-mocked behave pytest

behave:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add the comments for the each command (ideally on the same line as the command name) - see the comment about the help command below.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michael-paddle could you please add this? It is not super clear what each command does

behave --tags ~@future

pytest-mocked:
MOCK_AWS=true pytest

pytest:
pytest

wip: develop

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wip ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

work in progress - standard behave / BDD development acronym

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what Johan means is it is not clear what this command does.

behave --wip

lint:
pre-commit install --install-hooks
pre-commit run -a


# develop is needed to install scripts that are called during testing
develop: .develop.makestamp

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If needed, can we add setup command ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's useful; setup alone doesn't get you to a state where the test cases can pass. I'd rather not get that as something people expect to run until the time that we have it as a useful thing to do.

.develop.makestamp: setup.py backup_cloud_ssm/aws_ssm_cli.py $(LIBFILES)
$(PYTHON) setup.py install --force
$(PYTHON) setup.py develop
touch $@

.PHONY: all test behave pytest-mocked pytest wip lint develop

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to add the help command:

.SILENT: help
help: ## Shows all available commands
	set -x
	echo "Usage: make [target] ..."
	echo ""
	echo "Available targets:"
	grep ':.* ##\ ' ${MAKEFILE_LIST} | awk '{gsub(":[^#]*##","\t"); print}' | column -t -c 2 -s $$'\t' | sort

77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
Backup SSM parameter store to a file. Optional (but default)
encryption to be added.

## Using CLI tools

The CLI tool provides a simple interface to dump or restore the full
set of SSM parameters.

1) set up the appropriate environment including AWS variables

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be more specific ?
For example for DR, I would like just to copy/past steps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.


2) to backup run

aws-ssm-backup > `<filename>`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it requires to have the previous setup step run before ?
I tried to run the setup with ./setup.py and got permission denied: ./setup.py


3) to restore run

aws-ssm-backup --restore > `<filename>`

Special notes:

1) the tool does not overwrite - if you want to replace an existing
parameter, simply manually delete it and run again.

2) ssm seems to be eventually consistent - you will not want to update
SSM shortly before doing a backup. You may want to wait a second or
so after restoring.

## Using python interface

The backup and restore functions are provided as a libray. For backup

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libray -> library


import backup_aws_ssm
backup_aws_ssm.backup_to_file("myfile")

for restore:

import backup_aws_ssm
backup_aws_ssm.restore_from_file("myfile")

set the appropriate AWS variables to configure the aws region where
this will work.

## Using python ssm library

Included in the package is a library which provides a dict object
which accesses SSM parameter store. This will likely, later, be split out into a separate packge. In the meantime it can be used in Alpha testing mode.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packge -> package


from backup_cloud_ssm.aws_ssm_dict import aws_ssm_dict
ssm_dict = aws_ssm_dict()
ssm_dict["parameter"] = "value"
print(ssm_dict["parameter"])

SSM parameter store treats storing no description and storing the
empty description ("") as the same thing and will not return any
description. For simplicity we have now chosen to represent this as
the empty string. This decision may change in future and feedback is
appreciated.

When parameters are deleted the parameter description sometimes seems
to persist for some time, possibly only when it was '0'. Do not rely
on the description to be empty or see testing/test_parameter_storage
for how to handle this.


## Development

We aim to use Behavior Driven Development to encourage reasonable feature descriptions and a level of tests appropriate for the business functionality included here. Test Driven Development and to some extent Test Driven Design are encouraged in order to improve testability and eas of modification of the code.

Some of the tests are designed to run against either the Moto library or a real AWS instance. By defining the shell variable MOCK_AWS as "true" all of the tests which can be run in mocked form will be.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is part of README, can we have a link to the Moto library ?


export MOCK_AWS=true

This considerably speeds up testing but slightly increases risk since Moto's model of SSM is missing a number of features.

## Defined functionality

See the features directory for the supported features of the software. This is considered part of the documentation.
4 changes: 4 additions & 0 deletions backup_cloud_ssm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from backup_cloud_ssm.backup_aws_ssm import ( # noqa: F401
backup_to_file,
restore_from_file,
)
17 changes: 17 additions & 0 deletions backup_cloud_ssm/aws_ssm_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import argparse
import sys
import backup_cloud_ssm


def main():
parser = argparse.ArgumentParser(description="Backup AWS SSM Parameter Store")
parser.add_argument("--restore", help="restore from stdin", action="store_true")
args = parser.parse_args()
if args.restore:
backup_cloud_ssm.restore_from_file(sys.stdin)
else:
backup_cloud_ssm.backup_to_file(sys.stdout)


if __name__ == "__main__":
main()
Loading