aenv


Nameaenv JSON
Version 2.0.7 PyPI version JSON
download
home_pagehttps://github.com/MartinWie/AEnv
SummaryA Python 3 tool to fetch secure strings from the aws parameter store and injecting those into environment variables.
upload_time2024-01-31 21:10:58
maintainer
docs_urlNone
authorMartinWie
requires_python
licenseMIT
keywords aws aenv security parameterstore ssm cloud password
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # AEnv

[![OS](https://img.shields.io/badge/Runs%20on%3A-Linux%20%7C%20Mac%20%7C%20Windows-green)]() [![RunsOn](https://img.shields.io/badge/Used%20technologies-AWS%20%7C%20Python%203-green)]() [![RunsOn](https://img.shields.io/github/license/MartinWie/AEnv)](https://github.com/MartinWie/AEnv/blob/master/LICENSE) [![Open Source](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://opensource.org/)

![AEnv](https://github.com/MartinWie/AEnv/blob/master/AEnv_logo.png)

A Python-based CLI tool to simplify the process of fetching and injecting environment variables from AWS Parameter Store.

## Table of Contents

1. [Description](#description)
2. [Installation](#installation)
3. [Usage](#Usage)
4. [Setup](#Setup)
5. [Permissions](#Permissions)
6. [Concept](#Concept)
7. [Access-parameter-store-entries](#Access-parameter-store-entries)
8. [Authentication](#Authentication)
9. [Todos](#Todos)
10. [Acknowledgments](#Acknowledgments)
11. [License](#License)

## Description

This CLI tool (`aenv`) allows you to fetch environment variables from AWS Parameter Store, injecting them into your local environment for use in your applications. The tool also supports authentication with MFA, including Yubikeys.



## Installation

### Prerequisites

* Install python3 and pip

* [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
* Boto3 (Will be installed with the aenv package)
  * Windows: [setup Boto3 credentials](https://pypi.org/project/boto3/)


### Main Package (aenv)

```
pip install aenv
```



## Usage

```
aenv --help
# or
aenv -h
```

All current options:
```
aenv [-s <service/application>] [-i] [-n] [-e <env>] [-t <2fa key>] [-T] [-Y] [-u <aws username>] [-a <account number>] [-p <aws profile>] [-r <region>] <command>
```

| Option | Explanation | Sample | Comment |
| ------ | ----------- | ------ | ------- |
| -h | Shows help | `aenv -h` | |
| -i | Starts aenv in interactive mode | `aenv -i` | Gives you a command line that you can interact with |
| -s \<service/application> | For which service should the environment variables be loaded? | `aenv -s CustomerService` | |
| -S | Sets a default service for aenv and writes it to a config file | `aenv -S CustomerService` | from now on "CustomerService" is the default service which means "-s CustomerService" is redundant |
| -n | Do not query the parameter store at all  | `aenv -n` | Can be used to auth the current session with MFA |
| -e \<env> | For which environment should the environment variables be loaded? For example Dev, Test or Prod (permission required) | `aenv -e Prod` | |
| -t \<2fa key> | Takes the 2FA key from your aws account | `aenv -t 987123` | |
| -T | Lets you type in the 2FA key from your aws account during runtime | `aenv -T` | When you run your command aenv will ask for the token |
| -Y | Uses Yubikey for MFA auth | `aenv -Y` | During runtime aenv will use ykman to fetch the MFA-Key from your yubikey |
| -r \<region> | Overwrites temporary the awscli default region | `aenv -r eu-central-1` | aenv will use the given region for example Frankfurt |
| -v | Verbose mode (more output) | `aenv -v` | |
| -u \<aws username> | Sets a specific username combined with -a gives you a faster runtime (otherwise this data needs to be retrieved via aws) | `aenv -u user@example.de` | |
| -a \<account number> | Sets a specific account number combined with -u gives you a faster runtime (otherwise this data needs to be retrieved via aws) | `aenv -a 999999999999` | |
| -p \<aws profile> | If multiple aws profiles are available you can choose the profile otherwise aenv will use the default profile | `aenv -p testUser1` | |
| -c \<aws profile> | Container mode(enable this to make aenv work in ecs and codebuild) | `aenv -c` | [permissions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html) |
| \<command> | Is the command to execute with environment variables injected. | `aenv code` | Will run VS Code with access to given environment variables |



## Setup

Lets start with setting up a simple example service. Let's call it **UserService**. 

The **UserService** needs a **database hostname**, a **database username** and a **database password**. 

Let's assume, we have two environments, "Dev" and "Test" and we want to inject the correct **UserService**,  **database hostname**,... for the related environment.

Step 1 is to create the AWS parameter store entries.
Let's create two entries:

```
/Dev/UserService/DB/hostname
# and 
/Test/UserService/DB/hostname
```

Both are SecureString, that hold the values:
```
db.dev.example.com for /Dev/UserService/DB/hostname
and
db.test.example.com for /Test/UserService/DB/hostname
```

Step 2 is to fetch those values and have them available as environment variables.

For the **UserService** variables on Dev run:

```
aenv -e Dev -s UserService 
```
This command fetches all entries from the parameter store with the path /Dev/UserService/* and makes them available as environment variables.

If you just want to echo out the DB hostname we created (/Dev/UserService/DB/hostname) you can run:

```
aenv -e Dev -s UserService echo '$SECRET_USERSERVICE_DB_HOSTNAME'
```

You can also run your service with aenv to have the correct DB hostname available in the service as an environment variable.
The call for a Python or JVM service would be:

```
aenv -e Dev -s UserService java -jar service.jar
# or
aenv -e Dev -s UserService python service2.py
```

Both services now have access to the environment variable "SECRET_USERSERVICE_DB_HOSTNAME" containing the value that we defined for "/Dev/UserService/DB/hostname".

## Permissions

### Permissions (User)

Here is the minimal suggested set of IAM permissions to use aenv for all services that can be found for our Dev environment:

(Do not forget to adapt to account ID(123456789098) to your own )  

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParametersByPath",
                "ssm:GetParameters",
                "ssm:ListTagsForResource",
                "ssm:GetParameter"
            ],
            "Resource": [
                "arn:aws:ssm:*:123456789098:parameter/Dev/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "ssm:DescribeParameters",
            "Resource": "*"
        }
    ]
}
```
These permissions allow to fetch all entries for any service in the Dev environment.

For example, fetching all environment variables for a service called UserService:

```
aenv -e Dev -s UserService
```

To further limit access to only allow loading environment variables for a specific service like "UserService" we need to adapt the "Resource":

```
"Resource": [
                "arn:aws:ssm:*:123456789098:parameter/Dev/UserService/*"
            ]
```



#### Permissions (AWS)

This is a work in progress!

Currently, the yubikey needs to be added as a **virtual mfa** and needs to be the **first** device in our Multi-factor authentication devices.
Feel free to also add your Yubikey as a hardware mfa **afterwards**.(The AWS web console works flawless with multiple mfa's)

```
pip install --user yubikey-manager
```
[Official documentation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html)


## Permissions (IAM policies / Instance roles)

| Permission | Used in the code | Documentation | Comment 
| :- | :- | :- | :-
| "ec2:DescribeTags" | clientEC2.describe_tags() | https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeTags.html |
| "sts:GetCallerIdentity" | clientSTS.get_caller_identity() | https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html | Optional(No permissions are required to perform this operation.)
| "sts:GetSessionToken" | clientSTS.get_session_token() | https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html |
| "ssm:GetParametersByPath" | clientSSMMFA.get_parameters_by_path() | https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-access.html |
| "iam:ListMFADevices" | boto3.client('iam').list_mfa_devices() | https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_iam_mfa-selfmanage.html | Optional! (At the moment not in use but as soon aws API supports hardware tokens this can be enabled to let aenv support hardware MFA's) 

**tldr Minimal permissions:**

“ec2:DescribeTags”

“sts:GetSessionToken”

“ssm:GetParametersByPath”

### Advanced permission 1 (Enforce MFA authentication for accessing Prod parameters)

To enforce MFA authentication for all Prod parameters you can make use of the condition "MultiFactorAuthPresent" in your IAM permission.

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ssm:PutParameter",
                "ssm:DeleteParameter",
                "ssm:GetParameterHistory",
                "ssm:GetParametersByPath",
                "ssm:GetParameters",
                "ssm:ListTagsForResource",
                "ssm:GetParameter",
                "ssm:DeleteParameters"
            ],
            "Resource": [
                "arn:aws:ssm:*:123456789098:parameter/Prod/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ssm:DescribeParameters",
            "Resource": "*"
        }
    ]
}
```

### Advanced permission 2 (Enforce MFA authentication for AWS feature / function)

Add the condition "MultiFactorAuthPresent" to your IAM permission:

```
    "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
```

Sample for sts:AssumeRole: 

```
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {"AWS": "ACCOUNT-B-ID"},
    "Action": "sts:AssumeRole",
    "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
  }
}
```

Now you need MFA authentication to run assume role commands.
Sample call for this would be:

```
aenv -v -n -Y aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/example-role" --role-session-name AWSCLI-Session

# -v enables verbose mode
# -n puts aenv in only authentication mode
# -Y authenticates the session with your YubiKey, alternatively you could use -t or -T
```


## Concept

AEnv uses the parameter store path to define the environment and service name, following this schema:

```
/<Environment>/<Service-Name>/

# Which could look like:
/Prod/CustomerManagement/DB/USER
# Or
/Prod/CustomerManagement/DB/PASSWORD
```

Having those two in place would enable our **CustomerManagement** service running in our Prod environment to access, the environment variables:
SECRET_CUSTOMERMANAGEMENT_DB_USER
and 
SECRET_CUSTOMERMANAGEMENT_DB_PASSWORD

With both parameters in place, your **CustomerManagement** application/service, launched with aenv, could now access the database with the provided username and password.

```
aenv -e Prod -s CustomerManagement java -jar service.jar
```

#### Format for these environment variables:

Every environment variable that is loaded with aenv starts with "SECRET_".

Then the service-name and path, separated by underliners. (of course in upper case)

For example: 

```
/Prod/CustomerManagement/DB/USER
```

would be accessible with:

```
SECRET_CUSTOMERMANAGEMENT_DB_USER
```

or

```
/Prod/CustomerManagement/DB/PASSWORD/USER1
```

would be accessible with:

```
SECRET_CUSTOMERMANAGEMENT_DB_PASSWORD_USER1
```

More about environment variables: [Guide to Unix/Environment Variables](https://en.wikibooks.org/wiki/Guide_to_Unix/Environment_Variables)


## Access-parameter-store-entries

#### Testing single variables
**Linux/Mac**

```
aenv -e Dev -s UserService echo '$SECRET_USERSERVICE_UI_URL'
```

or

**Windows**

```
aenv -e Dev -s UserService echo %SECRET_USERSERVICE_UI_URL%  
```


### How to access the environment variables in Kotlin and Python

#### How to access the environment variables

To access those environment variables you have to run your application/service with aenv.

```
aenv -e Dev -s UserService java -jar service.jar
//or
aenv -e Dev -s UserService python service2.py
```

Now these two services have access to all Dev environment variables for the UserService.
Here are easy examples for Python and Kotlin:

**Python:**

```
import os
os.getenv('SECRET_USERSERVICE_HOSTNAME')

# For example conneting to a host depending on the environment:
....

hostname = os.getenv('SECRET_USERSERVICE_HOSTNAME')
....

```

**Kotlin:**

```
val envVar : String? = System.getenv("SECRET_USERSERVICE_HOSTNAME")
```

### Bonus:
#### Running a local application with access to environment variables of a given service

Linux/Mac running IntelliJ with Test environment variables for the **UserService**

```
aenv -e Test -s UserService "/Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS/idea"
```

This can come in handy if you want to debug something that only seems to occure in the Test environment. 



## Authentication

**AWS Server:**

Easy!

Done by boto3. Boto3 automatically uses the in the instance role defined permissions.

(Details "Permissions" section)

**Developer:**

boto3 uses the aws CLI's authentication so make sure you set this up before ;)

[AWS CLI](https://aws.amazon.com/cli/)

By default, aenv uses the aws CLI default profile, but of course, you can choose the profile, that you want to use, simply do:

```
aenv -p <awscli profile name>
#or 
aenv -h 
#to see more configuration options
```

(More details in the "Usage" section)

**MFA**

Multi-factor authentication is highly suggested!

https://lmgtfy.com/?q=why+mfa+is+important

Ok, all jokes aside especially for production parameters your IAM users should require MFA authentication at least for production parameters.

At least in my humble opinion, this should be a "better be safe than sorry" point.

Especially for your production systems!

AEnv supports multiple MFA options, details in the "Usage" section, here the short overview:

```
# Normal virtual mfa token:
aenv -t <TOKEN>

# Asks for the token during runtime:
aenv -T

# leads to an interactive token query during runtime:
$ aenv -T
$ Please enter token: 

#Yubikey Authenticator:
aenv -Y

```

## Todos

* Add managing mode with TerminalMenu to read specific values 
  * Function to add new entries
  * Function to update existing entries
  * Function to delete existing entries
* refactor whole code base
* Add better permission error handling (Especially the auth part with Yubikey handling)
* Add check if service exists/can be read with proper error message
* Update and correct -h / --help output
* Add regex filter for only loading specific variables
* Add regex filter to leave out variables from loading
* add -P to save a default profile
* Update initial setup instructions + console output for this(ykman + output for missing service)
* Option to list all available environments / services(discover/list env / list services)
* Check for ykman on -Y calls improve output
* Currently only the fist MFA device of any given account is used -> add mfa device selection + option for default selection
* cleanup/refactor documentation / improve overall structure
* add auth only mode(no env and no service name given)
* Add more information about container mode and necessary IAM permissions
* Enhance local profile/config setup/usage
* Handle the region in the same way services are handled
* Load multiple services at once instead of concatenating multiple aenv calls ( "aenv -s Service1 aenv -s Service2 ")
* Add feature for only loading certain variables to speed up loading
* Add assume role feature to support this setup more ease -> https://aws.amazon.com/de/blogs/security/enhance-programmatic-access-for-iam-users-using-yubikey-for-multi-factor-authentication/
* Add testing

## Acknowledgments 

**Inspired by:**

* **Gunnar Zarncke** - [LinkedIn](https://www.linkedin.com/in/gunnar-zarncke-952134163/) and his/troy gmbh's opensource credo projekt - [Git Credo](https://bitbucket.org/infomadis/troy-credo-aws/)

**Bug reports:**

* **[Arif PEHLİVAN](https://github.com/mrpehlivan)** 

* **[Carlos Freund](https://github.com/happyherp)**

## License

MIT [Link](https://github.com/MartinWie/AEnv/blob/master/LICENSE)

## Support me :heart: :star: :money_with_wings:
If this project provided value, and you want to give something back, you can give the repo a star or support by buying me a coffee.

<a href="https://buymeacoffee.com/MartinWie" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"></a>

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/MartinWie/AEnv",
    "name": "aenv",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "aws aenv security parameterstore ssm cloud password",
    "author": "MartinWie",
    "author_email": "donotsuspend@googlegroups.com",
    "download_url": "https://files.pythonhosted.org/packages/79/07/8d6455f26afa411c354daf9bec07433e59e5c27ac1d795a3821d7d64d747/aenv-2.0.7.tar.gz",
    "platform": null,
    "description": "# AEnv\n\n[![OS](https://img.shields.io/badge/Runs%20on%3A-Linux%20%7C%20Mac%20%7C%20Windows-green)]() [![RunsOn](https://img.shields.io/badge/Used%20technologies-AWS%20%7C%20Python%203-green)]() [![RunsOn](https://img.shields.io/github/license/MartinWie/AEnv)](https://github.com/MartinWie/AEnv/blob/master/LICENSE) [![Open Source](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://opensource.org/)\n\n![AEnv](https://github.com/MartinWie/AEnv/blob/master/AEnv_logo.png)\n\nA Python-based CLI tool to simplify the process of fetching and injecting environment variables from AWS Parameter Store.\n\n## Table of Contents\n\n1. [Description](#description)\n2. [Installation](#installation)\n3. [Usage](#Usage)\n4. [Setup](#Setup)\n5. [Permissions](#Permissions)\n6. [Concept](#Concept)\n7. [Access-parameter-store-entries](#Access-parameter-store-entries)\n8. [Authentication](#Authentication)\n9. [Todos](#Todos)\n10. [Acknowledgments](#Acknowledgments)\n11. [License](#License)\n\n## Description\n\nThis CLI tool (`aenv`) allows you to fetch environment variables from AWS Parameter Store, injecting them into your local environment for use in your applications. The tool also supports authentication with MFA, including Yubikeys.\n\n\n\n## Installation\n\n### Prerequisites\n\n* Install python3 and pip\n\n* [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)\n* Boto3 (Will be installed with the aenv package)\n  * Windows: [setup Boto3 credentials](https://pypi.org/project/boto3/)\n\n\n### Main Package (aenv)\n\n```\npip install aenv\n```\n\n\n\n## Usage\n\n```\naenv --help\n# or\naenv -h\n```\n\nAll current options:\n```\naenv [-s <service/application>] [-i] [-n] [-e <env>] [-t <2fa key>] [-T] [-Y] [-u <aws username>] [-a <account number>] [-p <aws profile>] [-r <region>] <command>\n```\n\n| Option | Explanation | Sample | Comment |\n| ------ | ----------- | ------ | ------- |\n| -h | Shows help | `aenv -h` | |\n| -i | Starts aenv in interactive mode | `aenv -i` | Gives you a command line that you can interact with |\n| -s \\<service/application> | For which service should the environment variables be loaded? | `aenv -s CustomerService` | |\n| -S | Sets a default service for aenv and writes it to a config file | `aenv -S CustomerService` | from now on \"CustomerService\" is the default service which means \"-s CustomerService\" is redundant |\n| -n | Do not query the parameter store at all  | `aenv -n` | Can be used to auth the current session with MFA |\n| -e \\<env> | For which environment should the environment variables be loaded? For example Dev, Test or Prod (permission required) | `aenv -e Prod` | |\n| -t \\<2fa key> | Takes the 2FA key from your aws account | `aenv -t 987123` | |\n| -T | Lets you type in the 2FA key from your aws account during runtime | `aenv -T` | When you run your command aenv will ask for the token |\n| -Y | Uses Yubikey for MFA auth | `aenv -Y` | During runtime aenv will use ykman to fetch the MFA-Key from your yubikey |\n| -r \\<region> | Overwrites temporary the awscli default region | `aenv -r eu-central-1` | aenv will use the given region for example Frankfurt |\n| -v | Verbose mode (more output) | `aenv -v` | |\n| -u \\<aws username> | Sets a specific username combined with -a gives you a faster runtime (otherwise this data needs to be retrieved via aws) | `aenv -u user@example.de` | |\n| -a \\<account number> | Sets a specific account number combined with -u gives you a faster runtime (otherwise this data needs to be retrieved via aws) | `aenv -a 999999999999` | |\n| -p \\<aws profile> | If multiple aws profiles are available you can choose the profile otherwise aenv will use the default profile | `aenv -p testUser1` | |\n| -c \\<aws profile> | Container mode(enable this to make aenv work in ecs and codebuild) | `aenv -c` | [permissions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html) |\n| \\<command> | Is the command to execute with environment variables injected. | `aenv code` | Will run VS Code with access to given environment variables |\n\n\n\n## Setup\n\nLets start with setting up a simple example service. Let's call it **UserService**. \n\nThe **UserService** needs a **database hostname**, a **database username** and a **database password**. \n\nLet's assume, we have two environments, \"Dev\" and \"Test\" and we want to inject the correct **UserService**,  **database hostname**,... for the related environment.\n\nStep 1 is to create the AWS parameter store entries.\nLet's create two entries:\n\n```\n/Dev/UserService/DB/hostname\n# and \n/Test/UserService/DB/hostname\n```\n\nBoth are SecureString, that hold the values:\n```\ndb.dev.example.com for /Dev/UserService/DB/hostname\nand\ndb.test.example.com for /Test/UserService/DB/hostname\n```\n\nStep 2 is to fetch those values and have them available as environment variables.\n\nFor the **UserService** variables on Dev run:\n\n```\naenv -e Dev -s UserService \n```\nThis command fetches all entries from the parameter store with the path /Dev/UserService/* and makes them available as environment variables.\n\nIf you just want to echo out the DB hostname we created (/Dev/UserService/DB/hostname) you can run:\n\n```\naenv -e Dev -s UserService echo '$SECRET_USERSERVICE_DB_HOSTNAME'\n```\n\nYou can also run your service with aenv to have the correct DB hostname available in the service as an environment variable.\nThe call for a Python or JVM service would be:\n\n```\naenv -e Dev -s UserService java -jar service.jar\n# or\naenv -e Dev -s UserService python service2.py\n```\n\nBoth services now have access to the environment variable \"SECRET_USERSERVICE_DB_HOSTNAME\" containing the value that we defined for \"/Dev/UserService/DB/hostname\".\n\n## Permissions\n\n### Permissions (User)\n\nHere is the minimal suggested set of IAM permissions to use aenv for all services that can be found for our Dev environment:\n\n(Do not forget to adapt to account ID(123456789098) to your own )  \n\n```\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ssm:GetParametersByPath\",\n                \"ssm:GetParameters\",\n                \"ssm:ListTagsForResource\",\n                \"ssm:GetParameter\"\n            ],\n            \"Resource\": [\n                \"arn:aws:ssm:*:123456789098:parameter/Dev/*\"\n            ]\n        },\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": \"ssm:DescribeParameters\",\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\nThese permissions allow to fetch all entries for any service in the Dev environment.\n\nFor example, fetching all environment variables for a service called UserService:\n\n```\naenv -e Dev -s UserService\n```\n\nTo further limit access to only allow loading environment variables for a specific service like \"UserService\" we need to adapt the \"Resource\":\n\n```\n\"Resource\": [\n                \"arn:aws:ssm:*:123456789098:parameter/Dev/UserService/*\"\n            ]\n```\n\n\n\n#### Permissions (AWS)\n\nThis is a work in progress!\n\nCurrently, the yubikey needs to be added as a **virtual mfa** and needs to be the **first** device in our Multi-factor authentication devices.\nFeel free to also add your Yubikey as a hardware mfa **afterwards**.(The AWS web console works flawless with multiple mfa's)\n\n```\npip install --user yubikey-manager\n```\n[Official documentation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html)\n\n\n## Permissions (IAM policies / Instance roles)\n\n| Permission | Used in the code | Documentation | Comment \n| :- | :- | :- | :-\n| \"ec2:DescribeTags\" | clientEC2.describe_tags() | https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeTags.html |\n| \"sts:GetCallerIdentity\" | clientSTS.get_caller_identity() | https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html | Optional(No permissions are required to perform this operation.)\n| \"sts:GetSessionToken\" | clientSTS.get_session_token() | https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html |\n| \"ssm:GetParametersByPath\" | clientSSMMFA.get_parameters_by_path() | https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-access.html |\n| \"iam:ListMFADevices\" | boto3.client('iam').list_mfa_devices() | https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_iam_mfa-selfmanage.html | Optional! (At the moment not in use but as soon aws API supports hardware tokens this can be enabled to let aenv support hardware MFA's) \n\n**tldr Minimal permissions:**\n\n\u201cec2:DescribeTags\u201d\n\n\u201csts:GetSessionToken\u201d\n\n\u201cssm:GetParametersByPath\u201d\n\n### Advanced permission 1 (Enforce MFA authentication for accessing Prod parameters)\n\nTo enforce MFA authentication for all Prod parameters you can make use of the condition \"MultiFactorAuthPresent\" in your IAM permission.\n\n```\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"VisualEditor0\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ssm:PutParameter\",\n                \"ssm:DeleteParameter\",\n                \"ssm:GetParameterHistory\",\n                \"ssm:GetParametersByPath\",\n                \"ssm:GetParameters\",\n                \"ssm:ListTagsForResource\",\n                \"ssm:GetParameter\",\n                \"ssm:DeleteParameters\"\n            ],\n            \"Resource\": [\n                \"arn:aws:ssm:*:123456789098:parameter/Prod/*\"\n            ],\n            \"Condition\": {\n                \"Bool\": {\n                    \"aws:MultiFactorAuthPresent\": \"true\"\n                }\n            }\n        },\n        {\n            \"Sid\": \"VisualEditor1\",\n            \"Effect\": \"Allow\",\n            \"Action\": \"ssm:DescribeParameters\",\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\n\n### Advanced permission 2 (Enforce MFA authentication for AWS feature / function)\n\nAdd the condition \"MultiFactorAuthPresent\" to your IAM permission:\n\n```\n    \"Condition\": {\"Bool\": {\"aws:MultiFactorAuthPresent\": \"true\"}}\n```\n\nSample for sts:AssumeRole: \n\n```\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": {\n    \"Effect\": \"Allow\",\n    \"Principal\": {\"AWS\": \"ACCOUNT-B-ID\"},\n    \"Action\": \"sts:AssumeRole\",\n    \"Condition\": {\"Bool\": {\"aws:MultiFactorAuthPresent\": \"true\"}}\n  }\n}\n```\n\nNow you need MFA authentication to run assume role commands.\nSample call for this would be:\n\n```\naenv -v -n -Y aws sts assume-role --role-arn \"arn:aws:iam::123456789012:role/example-role\" --role-session-name AWSCLI-Session\n\n# -v enables verbose mode\n# -n puts aenv in only authentication mode\n# -Y authenticates the session with your YubiKey, alternatively you could use -t or -T\n```\n\n\n## Concept\n\nAEnv uses the parameter store path to define the environment and service name, following this schema:\n\n```\n/<Environment>/<Service-Name>/\n\n# Which could look like:\n/Prod/CustomerManagement/DB/USER\n# Or\n/Prod/CustomerManagement/DB/PASSWORD\n```\n\nHaving those two in place would enable our **CustomerManagement** service running in our Prod environment to access, the environment variables:\nSECRET_CUSTOMERMANAGEMENT_DB_USER\nand \nSECRET_CUSTOMERMANAGEMENT_DB_PASSWORD\n\nWith both parameters in place, your **CustomerManagement** application/service, launched with aenv, could now access the database with the provided username and password.\n\n```\naenv -e Prod -s CustomerManagement java -jar service.jar\n```\n\n#### Format for these environment variables:\n\nEvery environment variable that is loaded with aenv starts with \"SECRET_\".\n\nThen the service-name and path, separated by underliners. (of course in upper case)\n\nFor example: \n\n```\n/Prod/CustomerManagement/DB/USER\n```\n\nwould be accessible with:\n\n```\nSECRET_CUSTOMERMANAGEMENT_DB_USER\n```\n\nor\n\n```\n/Prod/CustomerManagement/DB/PASSWORD/USER1\n```\n\nwould be accessible with:\n\n```\nSECRET_CUSTOMERMANAGEMENT_DB_PASSWORD_USER1\n```\n\nMore about environment variables: [Guide to Unix/Environment Variables](https://en.wikibooks.org/wiki/Guide_to_Unix/Environment_Variables)\n\n\n## Access-parameter-store-entries\n\n#### Testing single variables\n**Linux/Mac**\n\n```\naenv -e Dev -s UserService echo '$SECRET_USERSERVICE_UI_URL'\n```\n\nor\n\n**Windows**\n\n```\naenv -e Dev -s UserService echo %SECRET_USERSERVICE_UI_URL%  \n```\n\n\n### How to access the environment variables in Kotlin and Python\n\n#### How to access the environment variables\n\nTo access those environment variables you have to run your application/service with aenv.\n\n```\naenv -e Dev -s UserService java -jar service.jar\n//or\naenv -e Dev -s UserService python service2.py\n```\n\nNow these two services have access to all Dev environment variables for the UserService.\nHere are easy examples for Python and Kotlin:\n\n**Python:**\n\n```\nimport os\nos.getenv('SECRET_USERSERVICE_HOSTNAME')\n\n# For example conneting to a host depending on the environment:\n....\n\nhostname = os.getenv('SECRET_USERSERVICE_HOSTNAME')\n....\n\n```\n\n**Kotlin:**\n\n```\nval envVar : String? = System.getenv(\"SECRET_USERSERVICE_HOSTNAME\")\n```\n\n### Bonus:\n#### Running a local application with access to environment variables of a given service\n\nLinux/Mac running IntelliJ with Test environment variables for the **UserService**\n\n```\naenv -e Test -s UserService \"/Applications/IntelliJ\\ IDEA\\ CE.app/Contents/MacOS/idea\"\n```\n\nThis can come in handy if you want to debug something that only seems to occure in the Test environment. \n\n\n\n## Authentication\n\n**AWS Server:**\n\nEasy!\n\nDone by boto3. Boto3 automatically uses the in the instance role defined permissions.\n\n(Details \"Permissions\" section)\n\n**Developer:**\n\nboto3 uses the aws CLI's authentication so make sure you set this up before ;)\n\n[AWS CLI](https://aws.amazon.com/cli/)\n\nBy default, aenv uses the aws CLI default profile, but of course, you can choose the profile, that you want to use, simply do:\n\n```\naenv -p <awscli profile name>\n#or \naenv -h \n#to see more configuration options\n```\n\n(More details in the \"Usage\" section)\n\n**MFA**\n\nMulti-factor authentication is highly suggested!\n\nhttps://lmgtfy.com/?q=why+mfa+is+important\n\nOk, all jokes aside especially for production parameters your IAM users should require MFA authentication at least for production parameters.\n\nAt least in my humble opinion, this should be a \"better be safe than sorry\" point.\n\nEspecially for your production systems!\n\nAEnv supports multiple MFA options, details in the \"Usage\" section, here the short overview:\n\n```\n# Normal virtual mfa token:\naenv -t <TOKEN>\n\n# Asks for the token during runtime:\naenv -T\n\n# leads to an interactive token query during runtime:\n$ aenv -T\n$ Please enter token: \n\n#Yubikey Authenticator:\naenv -Y\n\n```\n\n## Todos\n\n* Add managing mode with TerminalMenu to read specific values \n  * Function to add new entries\n  * Function to update existing entries\n  * Function to delete existing entries\n* refactor whole code base\n* Add better permission error handling (Especially the auth part with Yubikey handling)\n* Add check if service exists/can be read with proper error message\n* Update and correct -h / --help output\n* Add regex filter for only loading specific variables\n* Add regex filter to leave out variables from loading\n* add -P to save a default profile\n* Update initial setup instructions + console output for this(ykman + output for missing service)\n* Option to list all available environments / services(discover/list env / list services)\n* Check for ykman on -Y calls improve output\n* Currently only the fist MFA device of any given account is used -> add mfa device selection + option for default selection\n* cleanup/refactor documentation / improve overall structure\n* add auth only mode(no env and no service name given)\n* Add more information about container mode and necessary IAM permissions\n* Enhance local profile/config setup/usage\n* Handle the region in the same way services are handled\n* Load multiple services at once instead of concatenating multiple aenv calls ( \"aenv -s Service1 aenv -s Service2 \")\n* Add feature for only loading certain variables to speed up loading\n* Add assume role feature to support this setup more ease -> https://aws.amazon.com/de/blogs/security/enhance-programmatic-access-for-iam-users-using-yubikey-for-multi-factor-authentication/\n* Add testing\n\n## Acknowledgments \n\n**Inspired by:**\n\n* **Gunnar Zarncke** - [LinkedIn](https://www.linkedin.com/in/gunnar-zarncke-952134163/) and his/troy gmbh's opensource credo projekt - [Git Credo](https://bitbucket.org/infomadis/troy-credo-aws/)\n\n**Bug reports:**\n\n* **[Arif PEHL\u0130VAN](https://github.com/mrpehlivan)** \n\n* **[Carlos Freund](https://github.com/happyherp)**\n\n## License\n\nMIT [Link](https://github.com/MartinWie/AEnv/blob/master/LICENSE)\n\n## Support me :heart: :star: :money_with_wings:\nIf this project provided value, and you want to give something back, you can give the repo a star or support by buying me a coffee.\n\n<a href=\"https://buymeacoffee.com/MartinWie\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-blue.png\" alt=\"Buy Me A Coffee\" width=\"170\"></a>\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python 3 tool to fetch secure strings from the aws parameter store and injecting those into environment variables.",
    "version": "2.0.7",
    "project_urls": {
        "Download": "https://github.com/MartinWie/AEnv/archive/2.0.6.tar.gz",
        "Homepage": "https://github.com/MartinWie/AEnv"
    },
    "split_keywords": [
        "aws",
        "aenv",
        "security",
        "parameterstore",
        "ssm",
        "cloud",
        "password"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "79078d6455f26afa411c354daf9bec07433e59e5c27ac1d795a3821d7d64d747",
                "md5": "3d1427da41cf1128546f866ee8bf1bf5",
                "sha256": "4ee203fe6e38774fdefb3af31296ae4b6fa75ee2d711cae8c047d2d92ffe4340"
            },
            "downloads": -1,
            "filename": "aenv-2.0.7.tar.gz",
            "has_sig": false,
            "md5_digest": "3d1427da41cf1128546f866ee8bf1bf5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 18576,
            "upload_time": "2024-01-31T21:10:58",
            "upload_time_iso_8601": "2024-01-31T21:10:58.938595Z",
            "url": "https://files.pythonhosted.org/packages/79/07/8d6455f26afa411c354daf9bec07433e59e5c27ac1d795a3821d7d64d747/aenv-2.0.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-31 21:10:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "MartinWie",
    "github_project": "AEnv",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "aenv"
}
        
Elapsed time: 0.73154s