simplygenius-atmos 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2 -0
  3. data/LICENSE +13 -0
  4. data/README.md +212 -0
  5. data/exe/atmos +4 -0
  6. data/exe/atmos-docker +12 -0
  7. data/lib/atmos.rb +12 -0
  8. data/lib/atmos/cli.rb +105 -0
  9. data/lib/atmos/commands/account.rb +65 -0
  10. data/lib/atmos/commands/apply.rb +20 -0
  11. data/lib/atmos/commands/auth_exec.rb +29 -0
  12. data/lib/atmos/commands/base_command.rb +12 -0
  13. data/lib/atmos/commands/bootstrap.rb +72 -0
  14. data/lib/atmos/commands/container.rb +58 -0
  15. data/lib/atmos/commands/destroy.rb +18 -0
  16. data/lib/atmos/commands/generate.rb +90 -0
  17. data/lib/atmos/commands/init.rb +18 -0
  18. data/lib/atmos/commands/new.rb +18 -0
  19. data/lib/atmos/commands/otp.rb +54 -0
  20. data/lib/atmos/commands/plan.rb +20 -0
  21. data/lib/atmos/commands/secret.rb +87 -0
  22. data/lib/atmos/commands/terraform.rb +52 -0
  23. data/lib/atmos/commands/user.rb +74 -0
  24. data/lib/atmos/config.rb +208 -0
  25. data/lib/atmos/exceptions.rb +9 -0
  26. data/lib/atmos/generator.rb +199 -0
  27. data/lib/atmos/generator_factory.rb +93 -0
  28. data/lib/atmos/ipc.rb +132 -0
  29. data/lib/atmos/ipc_actions/notify.rb +27 -0
  30. data/lib/atmos/ipc_actions/ping.rb +19 -0
  31. data/lib/atmos/logging.rb +160 -0
  32. data/lib/atmos/otp.rb +61 -0
  33. data/lib/atmos/provider_factory.rb +19 -0
  34. data/lib/atmos/providers/aws/account_manager.rb +82 -0
  35. data/lib/atmos/providers/aws/auth_manager.rb +208 -0
  36. data/lib/atmos/providers/aws/container_manager.rb +116 -0
  37. data/lib/atmos/providers/aws/provider.rb +51 -0
  38. data/lib/atmos/providers/aws/s3_secret_manager.rb +49 -0
  39. data/lib/atmos/providers/aws/user_manager.rb +211 -0
  40. data/lib/atmos/settings_hash.rb +90 -0
  41. data/lib/atmos/terraform_executor.rb +267 -0
  42. data/lib/atmos/ui.rb +159 -0
  43. data/lib/atmos/utils.rb +50 -0
  44. data/lib/atmos/version.rb +3 -0
  45. data/templates/new/config/atmos.yml +50 -0
  46. data/templates/new/config/atmos/runtime.yml +43 -0
  47. data/templates/new/templates.yml +1 -0
  48. metadata +526 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ff5c643bbfd1ad44992953679d7ace577ab60d541a0dd011c8455cb8627b5b2e
4
+ data.tar.gz: '017087621e3796fc796af5fd64cf3ccee30ad7025ba2ce146705e5ecf1f72235'
5
+ SHA512:
6
+ metadata.gz: e6631a0c431d37ea69b7e192bba5261211716af354bff2a9d7173f975be67b351a2ead91873969d0b6b7ae74dd8502830f8f6d2da5102c0eb17741b92878c745
7
+ data.tar.gz: fcf3687ec3436f764c7ee4307d27df149699171cf9276b68501428379f74b9922fce5ef7b9d28c956049715c1cec9c60f1dab931fb70c8fb72de04c5d82c950c
@@ -0,0 +1,2 @@
1
+ v0.7.0
2
+ First public release
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2018 SimplyGenius LLC
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,212 @@
1
+ [![Build Status](https://travis-ci.org/simplygenius/atmos.svg?branch=master)](https://travis-ci.org/simplygenius/atmos)
2
+ [![Coverage Status](https://coveralls.io/repos/github/simplygenius/atmos/badge.svg?branch=master)](https://coveralls.io/github/simplygenius/atmos?branch=master)
3
+
4
+ # Atmos
5
+
6
+ Atmos(phere) - Breathe easier with terraform
7
+
8
+ Atmos provides a layer of organization on top of terraform for creating cloud system architectures with Amazon Web Services. It handles the plumbing so you can focus on your application. The core atmos runtime is free and open-source, with a business friendly license (Apache). It provides some basic recipes to help get you going with a service oriented architecture implemented with AWS Elastic Container Services. For more in-depth recipes, please check out the Atmos Pro offering.
9
+
10
+ ## Goals
11
+
12
+ * The whole is greater than the sum of its parts. Assist in creating a cloud infrastructure _system_ rather than just discrete infrastructure components. Learning aws and terraform is a lot to bite off when getting started. It's much easier to start with a working system ,and learn incrementally as you go by making changes to it.
13
+
14
+ * The command line is king. Using a CLI to iterate on and manage core infrastructure has always been more effective for me, so I aim to make things as convenient and usable as possible from there.
15
+
16
+ * No lock-in. Since atmos just provides you convenience on top of using terraform, and the templates for defining your infrastructure are 99% in terraform, its possible to migrate away (albeit giving up all the convenience atmos provides) if your goals ever diverge from those of atmos.
17
+
18
+ * Your infrastructure is an important product. It should have its own repo and be tracked under configuration management, not just clickety-click-clicked on in a UI and promptly forgotten what it is you actually did to get there. The only guarantee you have, is that things are going to need to change, and you'll be much better off with a system that allows you to iterate easily. Atmos gets you started with minimal up-front knowledge, but provides a path for your infrastructure to evolve.
19
+
20
+ ## Features
21
+
22
+ * Manages AWS authentication, including MFA
23
+ * Integrated MFA token generation for convenience. This is technically not as secure since a laptop compromise exposes the key (vs a separate device for MFA). Plans to add yubikey support to get both convenience and security.
24
+ * Integrated secret management, with per-secret access permissions to minimize exposure footprint if something gets compromised
25
+ * Manages multiple independent environments (e.g. dev, staging, production), allowing them to be as similar or divergent as desired.
26
+ * Automates separation of environments across AWS accounts
27
+ * Secure by default
28
+ * Common recipe patterns to simplify maximal use of higher level AWS components.
29
+ * Sets up dns for your domain along with a wildcard certificate for hassle free ssl on your services
30
+ * Free and open source core with a business friendly license (Apache)
31
+
32
+
33
+ ## Installation
34
+
35
+ First install the dependencies:
36
+ * [Install docker](https://www.docker.com/community-edition) for deploying containers
37
+ * Install terraform (optional if running atmos as a docker image): e.g. `brew install terraform` on OS X
38
+ * Install the aws cli (optional, useful for managing aws credentials): e.g. `brew install aws` on OS X
39
+
40
+ Then install atmos:
41
+
42
+ To install as a gem:
43
+ * gem install simplygenius-atmos
44
+ * verify: `atmos --help`
45
+
46
+ To install/run as a docker image:
47
+ * curl -sL https://raw.githubusercontent.com/simplygenius/atmos/master/exe/atmos-docker > /usr/local/bin/atmos
48
+ * chmod +x /usr/local/bin/atmos
49
+ * verify: `atmos --help`
50
+
51
+ Note that when running as a docker image, UI notifications get forced inline as text output as atmos no longer has access to your current OS.
52
+
53
+ ## Usage
54
+
55
+ Usage is available via the command line: `atmos --help`
56
+ The [terraform docs](https://www.terraform.io/docs/index.html) are excellent.
57
+
58
+ ## Quickstart
59
+
60
+ See the [screencast](https://simplygenius.wistia.com/projects/h595iz9tbq) for a detailed walkthrough (~1 hour) of the quickstart.
61
+
62
+ [Create an AWS account](https://portal.aws.amazon.com/billing/signup)
63
+ Setup root account access keys, make note of the numeric account id
64
+
65
+ It'll make your life easier dealing with multiple keys if you make use of the AWS shared credential store. Save the access keys there with this command (picking your own name for the profile):
66
+
67
+ ```
68
+ aws configure --profile <root_profile_name>
69
+ ```
70
+
71
+ Create a new atmos project. This should only contain files defining your infrastructure, and not your application:
72
+
73
+ ```
74
+ mkdir my-ops-repo
75
+ cd my-ops-repo
76
+ atmos new
77
+ ```
78
+
79
+ Initialize the atmos project for aws. When prompted, input a short name for your organization and the AWS account id to use for the ops environment:
80
+
81
+ ```
82
+ atmos generate --force aws/scaffold
83
+ ```
84
+
85
+ The `--force` is optional and just prevents the prompt for every change the generator is making to files in your repo.
86
+
87
+ Optionally bring up config/atmos.yml in your editor and make any other desired changes.
88
+
89
+ Bootstrap your cloud provider to work with atmos. Answer `yes` when prompted to apply the changes.
90
+
91
+ ```
92
+ AWS_PROFILE=<root_profile_name> atmos -e ops bootstrap
93
+ AWS_PROFILE=<root_profile_name> atmos -e ops apply
94
+ ```
95
+
96
+ Setup a non-root user - using your email as the IAM username is convenient for email notifications in the future (e.g. per-user security validations like auto-expiry of access keys)
97
+
98
+ ```
99
+ AWS_PROFILE=<root_profile_name> atmos user create -l -k -g all-users -g ops-admin your@email.address
100
+ aws configure --profile <user_profile_name>
101
+ ```
102
+
103
+ If you supply the "-m" flag, it will automatically create and activate a virtual MFA device with the user, and prompt you to save the secret to the atmos mfa keystore for integrated usage. You can skip saving the secret and instead just copy/paste it into your MFA device of choice. The "user create" command can also act in more of an upsert fashion, so to do something like reset a user's password and keys, you could do `atmos user create --force -l -m -k your@email.address`
104
+
105
+ Login to the aws console as that user, change your password and setup MFA there if you prefer doing it that way. Make sure you log out and back in again with MFA before you try setting up the [role switcher](#per-user-role-switcher-in-console)
106
+
107
+ Now that a non-root user is created, you should be able to do everything as that user, so you can remove the root access keys if desired. Keeping them around can be useful though, as there are some AWS operations that can only be done as the root user. Leaving them in your shared credential store, but deactivating them in the AWS console till needed is a reasonable compromise.
108
+
109
+ While you can do everything in a single account, i've found a better practice is to use a new account for each env (dev, staging, prod, etc), and leave the ops account providing authentication duties and acting as a jumping off point to the others. This allows for easier role/permission management down the line as well as better isolation between environments, thereby enabling safe iteration in dev environments without risking production.
110
+
111
+ Create a new `dev` account, and bootstrap it to work with atmos
112
+
113
+ ```
114
+ AWS_PROFILE=<user_profile_name> atmos account create dev
115
+ AWS_PROFILE=<user_profile_name> atmos -e ops apply
116
+ AWS_PROFILE=<user_profile_name> atmos -e dev bootstrap
117
+ ```
118
+
119
+ Note that you can `export AWS_PROFILE=<user_profile_name>` in your environment, or keep using it per operation as preferred.
120
+
121
+ Use the 'aws/service' template to setup an ECS Fargate based service, then apply it in the dev environment to make it active. This template will also pull in some dependent templates to setup a vpc, dns for the provided domain and a wildcard cert to enable ssl for your service
122
+
123
+ ```
124
+ atmos generate --force aws/service
125
+ atmos -e dev apply
126
+
127
+ ```
128
+
129
+ Setup your application repo to work with ECS by generating a Dockerfile. For example, [here is the example app](https://github.com/simplygenius/atmos-example-app) used in the demo
130
+
131
+ To deploy your app to ECS, first use docker to build an image with a tag named the same as your service name
132
+
133
+ ```
134
+ # In your app repo directory
135
+ docker build -t <service_name> .
136
+ ```
137
+
138
+ Then use atmos to push and deploy that image to the ECR repo:
139
+
140
+ ```
141
+ atmos -e dev container deploy -c services <service_name>
142
+ ```
143
+
144
+ The atmos aws scaffold also sets up a user named deployer, with restricted permissions sufficient to do the deploy. Add the [key/secret](https://github.com/simplygenius/atmos-recipes/blob/master/aws/scaffold/recipes/atmos-permissions.tf#L159)) to the environment for your CI to get your CI to auto deploy on successful build.
145
+
146
+ ```
147
+ AWS_ACCESS_KEY_ID=<deployer_key> AWS_SECRET_ACCESS_KEY=<deployer_secret> atmos -e <env_based_on_branch> container deploy -c services <service_name>
148
+ ```
149
+
150
+ To clean it all up:
151
+
152
+ ```
153
+ # Applies flag to allow deleting empty buckets to existing resources
154
+ TF_VAR_force_destroy_buckets=true atmos -e dev apply
155
+
156
+ # Destroys all non-bootstrap resources create by atmos
157
+ atmos -e dev destroy
158
+
159
+ # Destroys the bootstrap resources (state, secret, lock storage and
160
+ # cross-account access role)
161
+ TF_VAR_force_destroy_buckets=true atmos -e dev apply --group bootstrap
162
+ atmos -e dev destroy --group bootstrap
163
+
164
+ # For normal usage you should rarely need to cleanup the ops account, but
165
+ # included here in case you want to completely purge the atmos resources after
166
+ # trying things out.
167
+
168
+ # Cleanup non-bootstrap ops
169
+ AWS_PROFILE=<root_profile_name> TF_VAR_force_destroy_buckets=true atmos -e ops apply
170
+ AWS_PROFILE=<root_profile_name> atmos -e ops destroy
171
+
172
+ # Cleanup ops bootstrap
173
+ AWS_PROFILE=<root_profile_name> TF_VAR_force_destroy_buckets=true atmos -e ops apply --group bootstrap
174
+ AWS_PROFILE=<root_profile_name> atmos -e ops destroy --group bootstrap
175
+
176
+ ```
177
+
178
+ These are separate commands so that day-day usage where you want to tear down everything (e.g. CI spinning up then destroying while testing) doesn't compromise your ability to use atmos/terraform. You can avoid the extra steps of applying with `TF_VAR_force_destroy_buckets=true` if you set `force_destroy_buckets: true` in atmos.yml
179
+
180
+ ## Per-User Role switcher in Console
181
+
182
+ If you are following the account-per-environment pattern, you will need to setup a role switcher for each account in the AWS console for your user. The AWS console seems to store these in cookies, so if you make a mistake its easy to fix by clearing them. First, login to the AWS console with your personal aws user that was created in the ops account. Select the dropdown with your email at top right of the page, Switch Role. Fill the details for the environment you want to be able to access from the console:
183
+
184
+ * Account number for the environment (See environments->`<env>`-> account_id in `config/atmos.yml`
185
+ * Role `<env>-admin` - this is the role you assume in the destination account.
186
+ * Pick a name (e.g. DevAdmin)
187
+ * Pick a color that you like (e.g. Red=production, Yellow=staging, Green=dev)
188
+
189
+ ## Managing secrets
190
+
191
+ Secrets are stored in a s3 bucket unique to each environment, and automatically passed into terraform when it is executed by atmos. The secret key should be the same as a terraform variable name defined in your terraform recipes, and if the secret exists, it will override whatever default value you have setup for the terraform variable.
192
+
193
+ To set a secret:
194
+
195
+ `atmos secret -e <env> set key value`
196
+
197
+ For other secret usage:
198
+
199
+ `atmos secret --help`
200
+
201
+ ## Contributing
202
+
203
+ Bug reports and pull requests are welcome on GitHub at https://github.com/simplygenius/atmos.
204
+
205
+
206
+ ## License
207
+
208
+ The gem is available as open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/apache-2.0).
209
+
210
+ # About Us
211
+
212
+ Simply Genius LLC is an independently run organization in Boston, MA USA. Its Chief Everything is Matt Conway, a software engineer and executive with more than 20 years of experience in the Boston Tech Startup scene. Atmos is his attempt at providing the world with the same tools, techniques, mindset and philosophy that he strives for when building a system architecture for a new startup.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/atmos/cli'
4
+ Atmos::CLI.run
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env sh
2
+
3
+ # fail fast
4
+ set -e
5
+
6
+ APP_VOLUME=${IMAGE_APP_VOLUME:-/app}
7
+
8
+ docker run \
9
+ --interactive --tty --rm \
10
+ --volume "$(pwd)":"${APP_VOLUME}" \
11
+ --volume /var/run/docker.sock:/var/run/docker.sock \
12
+ simplygenius/atmos "$@"
@@ -0,0 +1,12 @@
1
+ require_relative 'atmos/version'
2
+
3
+ require_relative 'atmos/logging'
4
+ Atmos::Logging.setup_logging(false, false, nil)
5
+
6
+ require_relative 'atmos/config'
7
+ require 'active_support/core_ext/string'
8
+ require 'active_support/concern'
9
+
10
+ module Atmos
11
+ mattr_accessor :config
12
+ end
@@ -0,0 +1,105 @@
1
+ require_relative '../atmos'
2
+ require_relative '../atmos/ui'
3
+ require 'clamp'
4
+ require 'sigdump/setup'
5
+
6
+ Dir.glob(File.join(File.join(__dir__, 'commands'), '*.rb')) do |f|
7
+ require_relative "commands/#{File.basename(f).sub(/\.rb$/, "")}"
8
+ end
9
+
10
+ module Atmos
11
+
12
+ # The command line interface to atmos
13
+ class CLI < Clamp::Command
14
+
15
+ include GemLogger::LoggerSupport
16
+
17
+ def self.description
18
+ desc = <<-DESC
19
+ Atmos version #{Atmos::VERSION}
20
+
21
+ Runs The atmos command line application
22
+
23
+ e.g.
24
+
25
+ atmos --help
26
+ DESC
27
+ desc.split("\n").collect(&:strip).join("\n")
28
+ end
29
+
30
+ option ["-d", "--debug"],
31
+ :flag, "debug output\n",
32
+ default: false
33
+
34
+ option ["-c", "--[no-]color"],
35
+ :flag, "colorize output (or not)\n (default: $stdout.tty?)"
36
+
37
+ option ["-e", "--atmos-env"],
38
+ 'ENV', "The atmos environment\n",
39
+ environment_variable: 'ATMOS_ENV', default: 'ops'
40
+
41
+ def default_color?
42
+ $stdout.tty?
43
+ end
44
+
45
+ option ["-l", "--[no-]log"],
46
+ :flag, "log to file in addition to terminal (or not)\n",
47
+ default: true
48
+
49
+
50
+ subcommand "new", "Sets up a new atmos project",
51
+ Atmos::Commands::New
52
+ subcommand "generate", "Generate recipes for the repository",
53
+ Atmos::Commands::Generate
54
+ subcommand "bootstrap", "Init cloud provider for use with atmos",
55
+ Atmos::Commands::Bootstrap
56
+ subcommand "init", "Run terraform init",
57
+ Atmos::Commands::Init
58
+ subcommand "plan", "Run terraform plan",
59
+ Atmos::Commands::Plan
60
+ subcommand "apply", "Run terraform apply",
61
+ Atmos::Commands::Apply
62
+ subcommand "destroy", "Run terraform destroy",
63
+ Atmos::Commands::Destroy
64
+ subcommand "terraform", "Run all other terraform commands",
65
+ Atmos::Commands::Terraform
66
+ subcommand "account", "Account management commands",
67
+ Atmos::Commands::Account
68
+ subcommand "user", "User management commands",
69
+ Atmos::Commands::User
70
+ subcommand "otp", "Otp tools",
71
+ Atmos::Commands::Otp
72
+ subcommand "secret", "Secret management commands",
73
+ Atmos::Commands::Secret
74
+ subcommand "auth_exec", "Authenticated exec",
75
+ Atmos::Commands::AuthExec
76
+ subcommand "container", "Container tools",
77
+ Atmos::Commands::Container
78
+
79
+ subcommand "version", "Display version" do
80
+ def execute
81
+ logger.info "Atmos Version #{Atmos::VERSION}"
82
+ end
83
+ end
84
+
85
+ subcommand "config", "Display expanded config for atmos_env" do
86
+ def execute
87
+ logger.info YAML.dump(Atmos.config.to_h)
88
+ end
89
+ end
90
+
91
+ # hook into clamp lifecycle to force logging setup even when we are calling
92
+ # a subcommand
93
+ def parse(arguments)
94
+ super
95
+ if Atmos.config.nil?
96
+ Atmos.config = Atmos::Config.new(atmos_env)
97
+ log = Atmos.config.is_atmos_repo? && log? ? "atmos.log" : nil
98
+ Atmos::Logging.setup_logging(debug?, color?, log)
99
+ Atmos::UI.color_enabled = color?
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,65 @@
1
+ require_relative 'base_command'
2
+ require_relative '../../atmos/settings_hash'
3
+ require 'climate_control'
4
+
5
+ module Atmos::Commands
6
+
7
+ class Account < BaseCommand
8
+
9
+ def self.description
10
+ "Manages accounts/envs in the cloud provider"
11
+ end
12
+
13
+ subcommand "create", "Create a new account" do
14
+
15
+ option ["-s", "--source-env"],
16
+ "SOURCE_ENV", "Base the new env on a clone of the given one\n"
17
+
18
+ option ["-e", "--email"],
19
+ "EMAIL", "override default email used for new account\n"
20
+
21
+ option ["-n", "--name"],
22
+ "NAME", "override default name used for new account\n"
23
+
24
+ parameter "ENV",
25
+ "The name of the new env to create"
26
+
27
+ def execute
28
+
29
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
30
+ ClimateControl.modify(auth_env) do
31
+
32
+ config = YAML.load_file(Atmos.config.config_file)
33
+
34
+ if config['environments'][env]
35
+ signal_usage_error "Env '#{env}' is already present in atmos config"
36
+ end
37
+
38
+ source = {}
39
+ if source_env.present?
40
+ source = config['environments'][source_env]
41
+ if source.blank?
42
+ signal_usage_error "Source env '#{source_env}' does not exist"
43
+ end
44
+ source = source.clone
45
+ end
46
+
47
+ account = Atmos.config.provider.account_manager.create_account(env, name: name, email: email)
48
+ logger.info "Account created: #{display account}"
49
+
50
+ source['account_id'] = account[:account_id].to_s
51
+
52
+ new_yml = Atmos::SettingsHash.add_config(
53
+ Atmos.config.config_file,
54
+ "environments.#{env}", source
55
+ )
56
+ logger.info("Writing out new atmos.yml containing new account")
57
+ File.write(Atmos.config.config_file, new_yml)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'terraform'
2
+
3
+ module Atmos::Commands
4
+
5
+ class Apply < Atmos::Commands::Terraform
6
+
7
+ def self.description
8
+ "Runs terraform apply"
9
+ end
10
+
11
+ def execute
12
+ args = ["apply"]
13
+ args << "--get-modules" unless Atmos.config["disable_auto_modules"].to_s == "true"
14
+ @terraform_arguments.insert(0, *args)
15
+ super
16
+ end
17
+
18
+ end
19
+
20
+ end