def init_accounts_yaml(self): """Process master account file and and create child account YAML files for the organization_account_ids field, if the child account YAML does not already exist.""" for org_account_id in self.master_account_config.organization_account_ids: # If account YAML already exists then skip it if org_account_id in self.paco_ctx.project['accounts'].keys(): continue # Account Check print("\nInitializing Account Configuration: %s\n" % (org_account_id)) account_config = None correct_value = False while correct_value == False: # Ask for Each Account Input account_config = { 'account_type': 'AWS', 'admin_delegate_role_name': 'Paco-Admin-Delegate-Role', 'region': None, 'title': None, 'root_email': None, } name_defaults = { 'prod': 'Production', 'dev': 'Development', } account_config['title'] = enhanced_input( " Title", self.get_account_default('title', org_account_id)) account_config['region'] = enhanced_input( " Region", self.get_account_default('region')) account_config['root_email'] = enhanced_input( " Root email address") # Verify the information collected print("\n--- %s Configuration ---" % org_account_id) yaml.dump(account_config, sys.stdout) print("---\n") correct_value = self.paco_ctx.input_confirm_action( "Is this the correct configuration for %s ?" % (org_account_id)) # Save account config to yaml account_yaml_path = os.path.join(self.paco_ctx.home, 'Accounts', org_account_id + ".yaml") with open(account_yaml_path, "w") as stream: yaml.dump(data=account_config, stream=stream)
def init_accounts(self): "Initialize Accounts" accounts_dir = os.path.join(self.paco_ctx.home, 'Accounts') master_account_file = loader.gen_yaml_filename(accounts_dir, 'master') with open(master_account_file, 'r') as stream: master_account_config = yaml.load(stream) print("\nAWS Account Initialization") print("---------------------------\n") if 'organization_account_ids' in master_account_config.keys(): print( "AWS Organization account names have already been defined: {}". format(','.join( master_account_config['organization_account_ids']))) else: print( "Enter a comma delimited list of account names to add to this project:" ) account_ids = enhanced_input("Account Names: ", 'prod,tools,security,data,dev') master_account_config[ 'organization_account_ids'] = account_ids.split(',') with open(master_account_file, 'w') as stream: yaml.dump(master_account_config, stream) # Loading the account controller will initialize the account yamls account_ctl = self.paco_ctx.get_controller('account') account_ctl.init_accounts_yaml()
def init_credentials(self, force=False): "Create a .credentials file for a Paco project" print("\nPaco project credentials initialization") print("---------------------------------------\n") if self.credentials_path.exists() and force == False: print("A .credentials file already exists at:\n{}.credentials\n". format(self.paco_ctx.home + os.sep)) sys.exit() master = self.paco_ctx.project['accounts']['master'] self.credentials['aws_default_region'] = master.region self.credentials['master_account_id'] = master.account_id self.credentials['master_admin_iam_username'] = enhanced_input( "Paco Admin Username", default='paco-admin') self.credentials['admin_iam_role_name'] = 'Paco-Admin-Delegate-Role' self.credentials['aws_access_key_id'] = enhanced_input( "AWS Access Key") self.credentials['aws_secret_access_key'] = enhanced_input( "AWS Secret Key") self.credentials['mfa_session_expiry_secs'] = 43200 self.credentials['assume_role_session_expiry_secs'] = 3600 try: os.chmod(self.credentials_path, stat.S_IRWXU) except FileNotFoundError: pass with open(self.credentials_path, "w") as output_fd: yaml.dump(data=self.credentials, stream=output_fd) os.chmod(self.credentials_path, stat.S_IRUSR) print("Paco credentials file created at:\n") print("%s\n" % self.credentials_path) print("It is NOT recommended to store this file in version control.") print( "Paco starter project include a .gitignore file to prevent this.") print( "You can store this file in a secrets mananger or re-create it again" ) print( "by generating a new AWS Api Key for the Paco Admin User and re-running" ) print("this 'paco init credentials' command.\n")
def init_project(self): "Create a Paco project skeleton from a template" starting_templates = { 'wordpress-single-tier': ("wordpresssingletier", "WordPress Single-Tier", "A single-tier WordPress application."), 'managed-webapp-cicd': ("managedwebappcicd", "Managed WebApp with CI/CD", "A managed web application with CI/CD and dev/staging/prod environments." ), 's3lambda': ("s3lambda", "S3 Bucket Lambda replicator", "An S3 Bucket that notifies a Lambda which replicates additions/deletions to S3 Bucket(s) in other regions." ), 'privatepypi': ("privatepypi", "Private PyPI server", "Private PyPI server with EFS filesystem behind a shared ALB."), 'simple-web-app': ("simplewebapp", "Empty skeleton project", "A minimal skeleton to be used as boilerplate for a from-scratch project." ), } print("\nPaco project initialization") print("---------------------------\n") if pathlib.Path(self.paco_ctx.home).exists(): print("Directory at {} already exists.\n".format( self.paco_ctx.home)) else: print( "A Paco project is a directory of YAML files that describes a cloud architecture," ) print("it's configuration and automation.\n") print( "This command will create a new ready-to-run Paco project. Choose a starter project," ) print( "answer some quesetions and a new Paco project directory will be created at:\n" ) print("%s\n" % self.paco_ctx.home) print( "Important: You will be asked to supply names. Paco names are short, alphanumeric identifiers." ) print( "Paco uses these names when creating cloud resources. After you provision resources" ) print( "with Paco it is not possible to change these names. You may also be asked for titles," ) print( "these can contain any characters (including spaces) and can be freely changed. Titles are used" ) print( "to help you organize your configuration more descriptively.") print() print("(Press Ctrl-D to abort)\n") name = self.choose_template(starting_templates) packagename = starting_templates[name][0] allowed_key_list = [] project_context = importlib.import_module( 'paco.cookiecutters.{}'.format( packagename)).get_project_context(self.paco_ctx) for key in project_context.keys(): if key.startswith('_computed_'): continue if key.endswith('_allowed_values'): continue if key == 'project_name': continue allowed_key = key + "_allowed_values" allowed_values = None if allowed_key in project_context.keys(): allowed_values = project_context[allowed_key] allowed_key_list.append(allowed_key) project_context[key] = enhanced_input( prompt_help_mapping[key], default=project_context[key], allowed_values=allowed_values) project_context['_computed_paco_home_path'] = self.paco_ctx.home project_context['master_admin_iam_username'] = '******' # Remove the allowed key so we do not save it to the context file for key in allowed_key_list: del project_context[key] # Massage account names into a de-duplicated list accounts = {} for key, value in project_context.items(): if key.endswith('_account'): accounts[value] = None project_context['accounts'] = '' for key in accounts.keys(): project_context['accounts'] += ' - ' + key + '\n' # short region name for second region (s3lambda) if 'aws_second_region' in project_context: project_context['short_region_list'] = vocabulary.aws_regions[ project_context['aws_second_region']]['short_name'] # budget Y or N to True or False if 'budget' in project_context: if project_context['budget'].lower().startswith('y'): project_context['budget'] = True else: project_context['budget'] = False cookiecutter(os.path.join(os.path.dirname(__file__), '..', 'cookiecutters', packagename), no_input=True, extra_context=project_context) # create the .gitignore seperately that filename can't be nested in git repo # tried using {{['.gitignore']|join}} but the | character is a problem on Windows filesystems fh = open(self.paco_ctx.home + os.sep + '.gitignore', 'w') fh.write(".credentials.yaml\n") fh.write(".credentials.yml\n") fh.write(".paco-work/build/\n") fh.close() print("\n\nPaco project created at:\n") print("%s\n" % self.paco_ctx.home) print( "It is recommended to export the PACO_HOME environment variable to tell Paco" ) print( "where your active Paco project is located, although you can also use the" ) print( "`paco --home=/your/path` flag. Consider adding this to your BASH profile.\n" ) print("export PACO_HOME=%s\n" % self.paco_ctx.home)