diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 0d31019..0000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-.sass-cache/
diff --git a/_site/2015/02/21/hello_world.html b/2015/02/21/hello_world.html
similarity index 100%
rename from _site/2015/02/21/hello_world.html
rename to 2015/02/21/hello_world.html
diff --git a/README.md b/README.md
deleted file mode 100644
index 9f5daeb..0000000
--- a/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Published at [http://l01cd3v.github.io](http://l01cd3v.github.io)
-
- $ # Commit a new blog post
- $ # Run jekyll to create new _site files
- $ jekyll serve
- $ # Commit new _site on source branch
- $ git add _site
- $ git push origin source
- $ git subtree push --prefix _site origin master
diff --git a/_config.yml b/_config.yml
deleted file mode 100644
index b9dd3b4..0000000
--- a/_config.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# This file contains configuration flags to customize your site
-#
-
-# Name of your site (displayed in the header)
-name: l01cd3v.github.io
-author: Loïc
-
-# Short bio or description (displayed in the header)
-description:
-
-# Pagination
-paginate: 5
-
-# Includes an icon in the footer for each username you enter
-footer-links:
- github: l01cd3v
- linkedin: loicsimon
- rss: f00 # just type anything here for a working RSS icon, make sure you set the "url" above!
-
-# Enter your Google Analytics web tracking code (e.g. UA-2110908-2) to activate tracking
-google_analytics: UA-56674561-3
-
-# Used for Sitemap.xml and your RSS feed
-url: http://l01cd3v.github.io
-
-#
-# !! You don't need to change any of the configuration flags below !!
-#
-
-markdown: redcarpet
-#highlighter: pygments
-gems: [jekyll-paginate]
-
-# Exclude these files from your production _site
-exclude:
- - Gemfile
- - Gemfile.lock
- - LICENSE
- - README.md
diff --git a/_includes/analytics.html b/_includes/analytics.html
deleted file mode 100644
index d8cdc0e..0000000
--- a/_includes/analytics.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% if site.google_analytics %}
-
-
-
-{% endif %}
diff --git a/_includes/isec.html b/_includes/isec.html
deleted file mode 100644
index d5ec1ee..0000000
--- a/_includes/isec.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- {% include analytics.html %}
-
-
diff --git a/_layouts/post.html b/_layouts/post.html
deleted file mode 100644
index 8b7dac1..0000000
--- a/_layouts/post.html
+++ /dev/null
@@ -1,5 +0,0 @@
----
-layout: default
----
-
-{% include post_body.html %}
diff --git a/_plugins/generate_categories.rb b/_plugins/generate_categories.rb
deleted file mode 100644
index 7cbeb5e..0000000
--- a/_plugins/generate_categories.rb
+++ /dev/null
@@ -1,240 +0,0 @@
-# encoding: utf-8
-#
-# Jekyll category page generator.
-# http://recursive-design.com/projects/jekyll-plugins/
-#
-# Version: 0.2.4 (201210160037)
-#
-# Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
-# Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-#
-# A generator that creates category pages for jekyll sites.
-#
-# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should
-# also create a file called 'category_index.html' in the _layouts directory of your jekyll site
-# with the following contents (note: you should remove the leading '# ' characters):
-#
-# ================================== COPY BELOW THIS LINE ==================================
-# ---
-# layout: default
-# ---
-#
-#
{{ page.title }}
-#
-# {% for post in site.categories[page.category] %}
-#
./RulesGenerator.py --ruleset_name isec --services iam
-1. Answer "yes" to the question "Would you like to ensure that all IAM users belong to a given IAM group?"
-1. Enter the name of your common group (*e.g.* AllUsers)
-1. Enter "yes" or "y" to confirm
-1. Change the level if desired
-1. Run Scout2
-
-***Note***: If you have already run Scout2 and do not wish to download the latest
-IAM configuration, use the following command to run an offline analysis:
-
- ./Scout2.py --ruleset_name isec --services iam --local
-
-The following screenshot illustrates the IAM menu dropdown containing a
-security risk when IAM users do not belong to the configured common group.
-
-
-
-When clicked-on, this link filters the list of IAM users to only display those
-who do not belong to the common IAM group. A colored warning sign appears,
-warning about this issue.
-
-
-
-### Conclusion
-
-Strict management of IAM users and tight control of their privileges is key in
-maintaining a secure AWS environment. When followed, the above recommendations
-should enable AWS administrators to manage IAM users with improved efficiency
-and lower the chances of overly privileged users to exist.
diff --git a/_posts/2015-04-02-use_and_enforce_mfa.markdown b/_posts/2015-04-02-use_and_enforce_mfa.markdown
deleted file mode 100644
index 9272f20..0000000
--- a/_posts/2015-04-02-use_and_enforce_mfa.markdown
+++ /dev/null
@@ -1,144 +0,0 @@
----
-layout: post
-title: "Use and enforce Multi-Factor Authentication"
-date: 2015-04-02 14:10
-post_author: Loïc Simon
-categories: AWS
-tags: iSEC
----
-
-### What is Multi-Factor Authentication?
-
-When enabled, Multi-Factor Authentication (MFA) provides strong
-defense-in-depth against compromises of credentials. MFA-enabled users have a
-device that periodically generates a new authentication code (*i.e.* one-time
-password); they need to enter the current authentication code along with their
-static credentials (*i.e.* username and password) in order to successfully
-authenticate. In addition to supporting MFA when accessing the web console
-(*i.e.* password-based authentication), AWS also offers MFA-protected API
-access for users who work with AWS access keys. Through the Security Token
-Service (STS), IAM users can request temporary credentials in exchange for
-their long-lived credentials (*i.e.* AWS access key ID and secret key) and
-their current authentication code.
-
-### Why should one use and enforce MFA?
-
-For companies deploying their application in the cloud, a breach that results
-in unauthorized access to the management console — or API — is the
-worst-case scenario. While a number of AWS administrators have realized the
-importance of enabling MFA when they access the web console, a limited number
-of them enforce MFA-protected API access. This represents a huge gap in one's
-security posture because AWS access keys do not come with as many security
-features as passwords do:
-
-* AWS administrators can enforce password expiration; this is currently not
-possible for AWS access keys.
-* While it is probably safe to assume that most AWS administrators do not store
-their password in plaintext, most of them use AWS access keys. By design, these
-keys are meant to be stored in plaintext files that are accessed by tools built
-with the various AWS SDKs.
-* A lost password is a forgotten password; a lost key is a key stored in a lost
-file, which may be on an unencrypted storage device (e.g. hard drive or USB Flash
-drive).
-
-Because AWS access keys are long-lived credentials that are stored in plaintext
-files, they are more susceptible to compromise than passwords. It is therefore
-necessary to enable MFA when the AWS API is accessed using these keys and not
-only when users sign in using their passwords.
-
-### How can one enforce MFA?
-
-Unfortunately, at time of writing, AWS does not offer an option to enforce
-MFA-protected API access via a global setting. Therefore, AWS account
-administrators must carefully manage their IAM users and develop a strategy to
-reliably achieve this. In order to enforce MFA-protected API access, iSEC
-recommends the following:
-
-1. Create a common IAM group that all IAM users belong to, as discussed in the previous [IAM user management strategy]({{ site.baseurl }}/aws/2015/02/24/iam_user_management.html) post.
-1. Add the following policy (also available on [Github](https://github.com/iSECPartners/AWS-recipes/blob/master/IAM-Policies/EnforceMFA-8HourSession.json)) to enforce MFA for all users who belong to this group.
-
-
-This policy will enforce MFA regardless of how the IAM user authenticated with
-AWS; it will be effective whether they use password-based or key-based
-authentication.
-
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Deny",
- "Action": "*",
- "Resource": "*",
- "Condition": {
- "Null":{"aws:MultiFactorAuthAge":"true"}
- }
- },
- {
- "Effect": "Deny",
- "Action": "*",
- "Resource": "*",
- "Condition": {
- "NumericGreaterThan":{"aws:MultiFactorAuthAge":"28800"}
- }
- }
- ]
- }
-
-
-The first statement in the above policy denies all actions if the
-*aws:MultiFactorAuthAge* key is not present; this key only exists if MFA is
-used [1].
-
-The second statement verifies that the validation of the MFA code was performed
-less than eight hours ago. Temporary credentials may be valid for a duration
-between fifteen minutes and thirty-six hours [2]. iSEC recommends requiring
-users to initiate a new session at least once a day.
-
-***Note:*** An "explicit deny" means that, regardless of other policies granted
-to a user, this deny rule will prevail. More information about the IAM policy
-evaluation logic can be found in the AWS documentation at http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html.
-
-### Use AWS Scout2 to detect users without MFA
-
-The default ruleset used by [AWS Scout2](https://github.com/iSECPartners/Scout2) includes a rule that checks for IAM users who have password-based authentication enabled but do not have an MFA device configured. If Scout2 detects IAM users with password-based authentication enabled and no MFA device, it will document a "Lack of MFA" security risk in the IAM menu dropdown, as illustrated in the below screenshot.
-
-
-
-When clicked, this "Lack of MFA" link filters the list of IAM users to display
-those who have password-based authentication enabled but no MFA device
-configured. The red "No" following "Multi-Factor enabled" indicates a danger
-tied to that particular IAM user.
-
-
-
-### How can one use MFA with command line tools?
-
-Users of the AWS CLI (and other command line tools) have several methods to
-configure their credentials, such as environment variables, configuration
-files, or command line arguments. However, updating these settings on a daily
-basis when MFA-protected API access is enabled is inconvenient. To help
-facilitate this work flow, iSEC has created a set of Python tools and released
-them in the [AWS-recipes](https://github.com/iSECPartners/AWS-recipes)
-repository. Further details about these tools will be published in the next
-blog post.
-
-Additional information about MFA with AWS is available in the AWS
-documentation at
-https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingMFA.html.
-
-
-### Conclusion
-
-Enforcing Multi-Factor Authentication for all IAM users is extremely important
-in order to mitigate the risks of credentials compromise (especially the AWS
-access key ID and secret). This aspect of security is commonly overlooked and
-may result in catastrophic damages. By using a strict strategy for management
-of IAM users and the above IAM policy, AWS administrators may significantly
-reduce risks of account compromise.
-
-[1] http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_ElementDescriptions.html#AvailableKeys
-
-[2] http://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html
diff --git a/_posts/2015-04-03-session_management_tools.markdown b/_posts/2015-04-03-session_management_tools.markdown
deleted file mode 100644
index b9e6b2b..0000000
--- a/_posts/2015-04-03-session_management_tools.markdown
+++ /dev/null
@@ -1,112 +0,0 @@
----
-layout: post
-title: "Work daily with enforced MFA-protected API access"
-date: 2015-04-03 14:10
-post_author: Loïc Simon
-categories: AWS
-tags: iSEC
----
-
-### AWS Security Token Service
-
-The AWS Security Token Service (STS) is the gateway used to create sessions
-when MFA-protected API access is enabled. This service allows IAM users to
-retrieve short-lived credentials (*i.e* access key ID, secret access key, and
-session token) in exchange for their long-lived credentials (*i.e.* AWS access
-key ID and secret key) and their current authentication code. When enforcing
-MFA-protected API access, as recommended in the previous [Use and enforce
-Multi-Factor
-Authentication]({{site.baseurl}}/aws/2015/04/02/use_and_enforce_mfa.html) post,
-IAM users must use these short-lived credentials to access other AWS services.
-
-### Challenges with MFA-protected API access
-
-When MFA-protected API access is enforced, managing AWS access keys becomes
-challenging because configuration files that contain these credentials must be
-updated regularly. Users must also ensure that they do not lose their
-long-lived credentials when modifying the configuration files to write their
-short-lived credentials. In order to help with this workflow, iSEC wrote and
-released several simple tools in the
-[AWS-recipes](https://github.com/iSECPartners/AWS-recipes) repository.
-
-The collection of tools that we will discussed below uses the "new
-and standardized way to manage credentials in the AWS SDKs", meaning that
-SDKs are expecting to read credentials from the *.aws/credentials* file under
-the user's home or profile directory.
-
-### aws\_recipes\_configure\_iam.py
-
-The
-[aws\_recipes\_configure\_iam.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_configure_iam.py)
-tool allows users to configure and store their long-lived credentials in a new,
-non-standard, *.aws/credentials.no-mfa* file. In addition to prompting for the
-AWS access key ID and secret key, this tool also prompts for the MFA device
-serial number because this information must be provided when making calls to
-the STS API. Similar to the AWS CLI and SDKs, it supports profile names. The
-following code snippet is an example of calling this tool to configure a new
-profile called *isecpartners*:
-
- $ ./aws_recipes_configure_iam.py --profile isecpartners
- AWS Access Key ID: AWS_KEY_ID
- AWS Secret Access Key: AWS_SECRET_KEY
- AWS MFA serial: arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
-
-When looking at the *.aws* folder, we can see that a *credentials.no-mfa* file
-exists and that it contains the credentials that were just entered:
-
- $ ls -l ~/.aws
- total 4
- -rw-r--r-- 1 loic loic 93 Apr 3 14:00 credentials.no-mfa
- $ cat ~/.aws/credentials.no-mfa
- [isecpartners]
- aws_access_key_id = AWS_KEY_ID
- aws_secret_access_key = AWS_SECRET_KEY
- aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
-
-Now that long-lived credentials are configured, we can use the next tool to
-call the AWS STS API and request short-lived credentials that will be used
-to access other AWS services.
-
-### aws\_recipes\_init\_sts\_session.py
-
-The
-[aws\_recipes\_init\_sts\_session.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py)
-tool reads long-lived credentials configured in the .aws/credentials.no-mfa
-file, prompts users for their MFA code, and retrieves STS credentials (AWS
-access key ID, AWS secret key, and session token). The short-lived credentials
-are then saved under the standardized *.aws/credentials* file to be accessible
-to the AWS CLI and other tools built with the AWS SDKs. The following code
-snippet demonstrates calling this tool to request an STS session token:
-
- $ ./aws_recipes_init_sts_session.py --profile isecpartners
- Enter your MFA code: 123456
- Successfully configured the session token for profile 'isecpartners'.
-
-When looking at the *.aws* folder, we can see that a standard *credentials*
-file now exists as well and that it contains the short-lived credentials:
-
- $ ls -l ~/.aws
- total 8
- -rw-r--r-- 1 loic loic 576 Apr 3 14:14 credentials
- -rw-r--r-- 1 loic loic 179 Apr 3 14:00 credentials.no-mfa
- $ cat ~/.aws/credentials
- [isecpartners]
- aws_access_key_id = STS_KEY_ID
- aws_secret_access_key = STS_SECRET_KEY
- aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
- aws_session_token = AWS//////////SESSION_TOKEN
-
-Now that the short-lived credentials are configured, we can use the AWS CLI or
-other tools built with the AWS SDKs that read credentials from this standard
-location. When the STS session expires, users just need to re-run the
-[aws\_recipes\_init\_sts\_session.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py)
-tool and the standard *credentials* file will be updated with new valid
-short-lived credentials.
-
-### Conclusion
-
-By using this pair of tools to manage their AWS access keys, IAM users can
-easily use the AWS CLI and other tools built with various AWS SDKs in
-environments that have been secured and enforce MFA-protected API access.
diff --git a/_posts/2015-06-09-iam_user_management_2.markdown b/_posts/2015-06-09-iam_user_management_2.markdown
deleted file mode 100644
index 8f4cb59..0000000
--- a/_posts/2015-06-09-iam_user_management_2.markdown
+++ /dev/null
@@ -1,155 +0,0 @@
----
-layout: post
-title: "IAM user management strategy (part 2)"
-date: 2015-06-09 09:20
-post_author: Loïc Simon
-categories: AWS
-tags: iSEC
----
-
-The previous [IAM user management strategy]
-({{{site.baseurl}}/aws/2015/02/24/iam_user_management.html) post discussed how
-usage of IAM groups enables AWS administrators to consistently grant privileges
-and enforce a number of security rules (such as MFA-protected API access). This
-blog post will build on this idea by introducing category groups and
-documenting new tools to improve IAM user management.
-
-### Categorize your IAM users
-
-For a variety of reasons, applying a single set of security rules to all IAM
-users is not always practical. For example, because many applications running
-in AWS predate IAM roles, numerous environments still rely on the existence of
-headless IAM users. Additionally, third parties may be granted access to an AWS
-account for a number of reasons but may not be able to comply with the same set
-of security rules that employees follow. For this reason, NCC recommends using
-category groups to sort IAM users and reliably enforce appropriate security
-measures. For example, one group for all human users and a second for all headless users may be
-created: MFA-protected API access and password management are not relevant for
-headless users. Furthermore, human users may be categorized into several groups
-such as employees and contractors: API access can be restricted to the
-corporate IP range for employees but might not be achievable for contractors.
-
-*Note 1:* The set of category groups should define all types of IAM users that
-may exist in your AWS account and each IAM user should belong to one -- and
-only one -- category group (they may belong to other groups though).
-
-*Note 2:* The common group and category groups should be used to enable enforcing
-security in one's AWS environment. Policies attached to these groups should be
-carefully reviewed and grant the minimum set of privileges necessary for this
-type of IAM user (*e.g.* credential management for humans).
-
-### Example of category groups
-
-The rest of this article describes a number of tools developed and used by
-NCC to help implement this IAM user management strategy. These tools can be found
-in the [AWS-Recipes](https://github.com/iSECPartners/AWS-recipes) repository. We will
-use our test AWS environment as an example, in which we use three category groups in
-addition to the *AllUsers* common group:
-
-1. *AllHumans*, the group all employees must belong to.
-1. *AllHeadlessUsers*, the group all headless IAM users must belong to.
-1. *AllMisconfiguredUsers*, a placeholder for sample misconfigured users.
-
-We also have an IAM user naming convention that requires usernames to match the
-following schema:
-
-1. Employees: firstname initial appended with lastname
-1. Headless user: name of the service prefixed with *HeadlessUser-*
-1. Misconfigured: description of the misconfiguration prefixed with *MisconfiguredUser-*
-
-Based on these rules, we created a configuration file stored under
-*.aws/recipes/isecpartners.json*, with *isecpartners* matching the profile's
-name. If you do not use profiles, the configuration will be under
-*.aws/recipes/default.json*.
-
- {
- "common_groups": [ "AllUsers" ],
- "category_groups": [
- "AllHumanUsers",
- "AllHeadlessUsers",
- "AllMisconfiguredUsers"
- ],
- "category_regex": [
- "",
- "^Headless-(.*)",
- "^MisconfiguredUser-(.*)"
- ],
- "profile_name": [ "isecpartners" ]
- }
-
-
-This configuration file declares the name of the common IAM group and two lists
-related to the categorization of IAM users:
-
-1. A list of category groups.
-1. A list of regular expressions matching our naming convention.
-
-
-*Note 1:* If you do not have a naming convention in place to distinguish the
-type of user, remove the *category_regex* attribute from your configuration
-file.
-
-*Note 2:* If a regular expression is only applicable to a subset of category
-groups, you must ensure that both lists have the same length and use an empty
-string for groups that cannot be automatically associated (see the
-*AllHumanUsers* group in our example).
-
-*Note 3:* Use of a configuration file is not necessary as all values may be
-passed as command line arguments. If a configuration file exists and a value is
-passed as an argument, the value passed via the command line will be used.
-
-### Create your default groups with *[aws\_iam\_create\_default\_groups.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_default_groups.py)*
-
-The purpose of this tool is to create IAM groups whose name matches the common
-and category groups specified in the above configuration file. Running the
-following command results in four new groups being created if they did not
-already exist.
-
- ./aws_iam_create_default_groups.py --profile isecpartners
-
-### (Automatically) sort IAM users with *[aws\_iam\_sort\_users.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_sort_users.py).*
-
-This tool iterates through all IAM users and attempts to automatically detect
-the IAM groups each user should belong to. For convenience, we recommend adding
-the following to your AWS recipes configuration files:
-
- "aws_sort_users.py": {
- "create_groups": false,
- },
- "force_common_group": true
-
-This specifies default values for additional arguments to be set when running
-*aws\_iam\_sort\_users.py*. Specifically, with these values, running this tool
-will automatically add all IAM users to the common group *AllUsers* and will
-not attempt to create the default groups (not necessary as we already did
-this). Additionally, this tool checks that each IAM user belongs to one of the
-category groups. If this is not the case and the username matches a regular
-expression, the user is automatically added to the matching category group. Otherwise, a
-multi-choice prompt appears to allow manual selection of the appropriate
-category group.
-
-### Additional advantages of configuration files
-
-Besides helping with simplification of these tools' usage, this new AWS-recipe
-configuration file can be used across tools, allowing for more consistent
-rule enforcement. For example, the
-*[aws\_iam\_create\_user.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_user.py).*
-tool uses this configuration file and applies the same business logic to add
-users to the common group and appropriate category group at user creation time. In
-our test environment, for example, running the following command automatically
-added the new user to the *MisconfiguredUser* group:
-
- $ ./aws_iam_create_user.py --profile isecpartners --users MisconfiguredUser-BlogPostExample
- Creating user MisconfiguredUser-BlogPostExample...
- Save unencrypted value (y/n)? y
- User 'MisconfiguredUser-BlogPostExample' does not belong to the mandatory common group 'AllUsers'. Do you want to remediate this now (y/n)? y
- User 'MisconfiguredUser-BlogPostExample' does not belong to any of the category group (AllHumanUsers, AllHeadlessUsers, AllMisconfiguredUsers). Automatically adding...
- Enabling MFA for user MisconfiguredUser-BlogPostExample...
-
-### Conclusion
-
-While efficient and reliable management of IAM users can be challenging, using
-the right strategy and tools significantly simplifies this process. Creation
-and use of a naming convention for IAM users enables
-automated user management and enforcement of security rules.
-
diff --git a/_posts/2015-08-03-boto3_opinel_scout_recipes.markdown b/_posts/2015-08-03-boto3_opinel_scout_recipes.markdown
deleted file mode 100644
index ecd24e5..0000000
--- a/_posts/2015-08-03-boto3_opinel_scout_recipes.markdown
+++ /dev/null
@@ -1,86 +0,0 @@
----
-layout: post
-title: "Introducing opinel: Scout2's favorite tool"
-date: 2015-08-03 11:08
-post_author: Loïc Simon
-categories: AWS
-tags: iSEC
----
-
-With boto3 being stable and generally available[1], I took the opportunity
-to migrate Scout2 and AWS-recipes to boto3. As part of that migration
-effort, I decided to publish the formerly-known-as AWSUtils repository -- used
-by Scout2 and AWS-recipes -- as a python package required by these tools,
-rather than requiring users to work with Git submodules. I've also added more
-flexibility when working with MFA-protected API calls and improved versioning
-across the project.
-
-### opinel
-
-To avoid name conflicts, I decided to rename the shared AWSUtils code to a
-less misleading name: opinel. The opinel package is published on [PyPI](https://pypi.python.org/pypi/opinel), and thus can
-be installed using pip and easy\_install. The corresponding source code is still
-open-sourced on Github at [https://github.com/iSECPartners/opinel](https://github.com/iSECPartners/opinel).
-As a result, Scout2 and AWS-recipes have been modified to list opinel as a
-requirement, which significantly simplifies installation and management of this
-shared code.
-
-### Support for Python 2.7 and 3.x
-
-Because boto3 supports both Python2 and Python3, I decided to make sure that
-the code built on top of that package has similar properties. As a result,
-the latest versions of Scout2 and AWS-recipes support Python 2.7 and 3.x.
-Note that opinel will **NOT** work with Python 2.6.
-
-### Modification of the MFA workflow
-
-As requested by a user of AWS-recipes[2], I modified the workflow when
-using MFA-protected API access to no longer store the long-lived credentials
-in a separate file. As a result, the *.aws/credentials.no-mfa* file is no
-longer supported and all credentials are stored in the standard AWS credentials
-file under *.aws/credentials*. Usage of the existing tools remains unchanged,
-but the long-lived credentials are now accessible via a new profile name:
-*profile\_name-nomfa*. This allows users to work with both STS and long-lived
-credentials if need be.
-
-If you already had configured your environment to work with MFA-protected API
-access, you will need to copy your long-lived credentials back to the
-*.aws/credentials* file. This can be done with a simple command such as the
-following:
-
- cat ~/.aws/credentials.no-mfa | sed -e 's/]$/-nomfa]/g' >> ~/.aws/credentials
-
-### Support to use assumed-role credentials
-
-With this new workflow implemented, I created a new recipe that allows
-configuration of role-credentials in the *.aws/credentials* file. When the following
-command is run, it uses the credentials associated with the *isecpartners*
-profile to request role credentials for the IAM-Scout2 role. The role
-credentials are then written in the *.aws/credentials* file in a new profile
-named *isecpartners-Scout2*, which is the profile name appended by the role
-session name.
-
- $ ./aws_recipes_assume_role.py --profile isecpartners --role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/IAM-Scout2 --role-session-name Scout2
-
-Users can then use their favorite tools that support profiles. For example,
-Scout2 could be run with the following command line:
-
- $ ./Scout2.py --profile isecpartners-Scout2
-
-Note that this recipe supports MFA if the assumed role requires it:
-
- * If you never configured your environment to work with MFA, you can provide your MFA serial number (ARN) and current token code as arguments.
- * If you already configured your environment to work with MFA and stored your MFA serial in the *.aws/credentials* file, you just need to pass your token code as an additional argument.
- * Finally, if you already initiated an STS session, you do not need to provide a new token code and can run the command as above.
-
-### Conclusion
-
-With the release of opinel, I hope to simplify distribution and management of
-the code shared between Scout2 and AWS-recipes. Additionally, I
-significantly modified the workflow and credentials storage when working with
-MFA-protected API calls, which allows users to use both their long-lived and STS
-credentials.
-
-[1]: https://aws.amazon.com/about-aws/whats-new/2015/06/boto3-aws-sdk-for-python-version-3-is-now-generally-available
-
-[2]: https://github.com/iSECPartners/opinel/issues/4
diff --git a/_posts/2015-08-06-scout2_supports_redshift.markdown b/_posts/2015-08-06-scout2_supports_redshift.markdown
deleted file mode 100644
index a8769bf..0000000
--- a/_posts/2015-08-06-scout2_supports_redshift.markdown
+++ /dev/null
@@ -1,34 +0,0 @@
----
-layout: post
-title: "Redshift support added in Scout2"
-date: 2015-08-06 08:39
-post_author: Loïc Simon
-categories: AWS
-tags: NCC
----
-
-Today, I am excited to announce that support for Redshift was added in
-Scout2. By default, Scout2 will fetch information about your Redshift clusters,
-cluster parameter groups, and cluster security groups if you still use
-EC2-Classic. At this stage, Scout2 comes with six Redshift security rules that
-are enabled by default:
-
- * Clusters
- * Check whether version upgrade is enabled
- * Check whether the cluster is publicly accessible
- * Check whether database encryption is enabled
- * Cluster parameter groups
- * Check whether SSL/TLS is required to access the database
- * Check whether user activity logging is enabled
- * Cluster security groups (EC2-classic)
- * Check whether the security group allows access to all IP addresses (0.0.0.0/0)
-
-Scout2 was first released over a year and a half ago, and proved to be extremely
-helpful when performing AWS configuration reviews. While
-Scout2's initial release only supported three services (IAM, EC2, and S3) and
-included thirteen security checks, the tool rapidly grew to add support for RDS
-and CloudTrail. Furthermore, the tool now offers over fifty tests throughout
-these five supported services. I hope that support for Redshift will bring
-value to users of Scout2, and welcome feature requests, bug reports, and
-recommendations on Github at
-[https://github.com/iSECPartners/Scout2/issues](https://github.com/iSECPartners/Scout2/issues).
diff --git a/_posts/2015-11-17-ip_ranges_management.markdown b/_posts/2015-11-17-ip_ranges_management.markdown
deleted file mode 100644
index 1ff9818..0000000
--- a/_posts/2015-11-17-ip_ranges_management.markdown
+++ /dev/null
@@ -1,302 +0,0 @@
----
-layout: post
-title: "Efficient review of AWS security groups' CIDR grants"
-date: 2015-11-17 08:00
-post_author: Loïc Simon
-categories: AWS
-tags: NCC
----
-
-A significant challenge for companies using the cloud lies in ensuring that
-their firewall rules follow the principle of least privilege. It is
-extremely common nowadays to delegate management of security groups to developers, for
-both production and test environments. This means that security groups and
-their associated rules are managed by a much larger number of employees than
-what used to be the case in non-cloud environments, where a unique, smaller
-team was in charge of managing all firewall rules. Due to the more dynamic
-nature of cloud-based infrastructures, companies should review their cloud
-environment's firewall rules on a more frequent basis than for non cloud-based
-systems. Unfortunately, this is a difficult exercise due to the large number of
-[CIDRs](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) that may be whitelisted in a given AWS account. Keeping track of all
-known CIDRs and what hosts or networks they represent is not easy for
-employees, and is almost impossible for external auditors who must perform the
-review within a limited timeframe.
-
-In this post, I will document how this issue can be addressed using the
-[AWS-Recipes](https://github.com/iSECPartners/AWS-recipes) tools and
-[Scout2](https://github.com/iSECPartners/Scout2).
-
-### Feed custom ip-ranges files to Scout2
-
-Today, I am excited to announce that Scout2 accepts JSON files that
-contain known CIDRs along with arbitrary metadata such as the host or network
-they represent. When provided with such files, Scout2's report displays the
-"friendly name" of each known CIDR that is whitelisted in security group rules.
-This means that, instead of reviewing a list of obscure IP ranges, users of
-Scout2 may now rely on the name associated with each CIDR.
-
-In order to use this new feature, Scout2 should be run with the following
-arguments:
-
- ./Scout2.py --profile nccgroup --ip-ranges ip-ranges-nccgroup.json ip-ranges-ncc-offices.json --ip-ranges-key-name name
-
-In the above command line, Scout2 receives two ip-ranges JSON files via the
-"--ip-ranges" argument:
-
- * ip-ranges-nccgroup.json, which contains the public IP addresses in the AWS IP space in use
- * ip-ranges-ncc-offices.json, which contains the public IP addresses of several offices
-
-Furthermore, the "--ip-ranges-key-name" argument indicates which JSON field to
-display as the "friendly name".
-
-The following screenshot illustrates that, in the Scout2 report, the name of
-each known CIDR is displayed. When an IP which belongs to a known CIDR is
-whitelisted, the name of the corresponding CIDR is used. In this example,
-5.5.5.42/32 belongs to the 5.5.5.0/24 CIDR, which is associated with the "San
-Francisco" office. An "Unknown CIDR" value is displayed when an unknown value
-is whitelisted.
-
-
-
-The next section of this blog post documents how users can create and manage
-these ip-ranges JSON files.
-
-### Manage known CIDRs with aws\_recipes\_create\_ip\_ranges.py
-
-With AWS releasing their public IP address ranges, I decided to create a tool
-that allows creation and management of arbitrary IP address ranges using the
-same JSON format. The tool is released on GitHub at
-[https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws\_recipes\_create\_ip\_ranges.py](https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_create_ip_ranges.py)
-and may be used in several scenarios:
-
- * Automatically create ip-ranges files based on public IP addresses in AWS (Elastic IPs and EC2 instances)
- * Automatically create ip-ranges files based on IP addresses documented in a CSV file
- * Manually create and manage ip-ranges files
-
-Each of these use cases is detailed in an example below, with detailed input,
-commands, and output contents.
-
-***Note:*** In the commands below, the "--debug" argument is used to
-output pretty-printed JSON, for documentation purposes.
-
-#### Automatically create ip-ranges based on public IP addresses in an AWS account
-
-First, this tool may be used to create an ip-ranges file that contains an AWS
-account's elastic IP addresses and EC2 instances' public IP addresses. By doing
-so, AWS users will be able to maintain a list of public IP addresses in the AWS
-IP space that are associated with their resources. Assuming that AWS
-credentials are configured under the "nccgroup" profile name, the command
-below may be used:
-
- $ ./aws_recipes_create_ip_ranges.py --profile nccgroup --debug
-
- Fetching public IP information for the 'nccgroup' environment...
- ...in us-east-1: EC2 instances
- ...in us-east-1: Elastic IP addresses
- ...in ap-northeast-1: EC2 instances
- ...in ap-northeast-1: Elastic IP addresses
- ...in eu-west-1: EC2 instances
- ...in eu-west-1: Elastic IP addresses
- ...in ap-southeast-1: EC2 instances
- ...in ap-southeast-1: Elastic IP addresses
- ...in ap-southeast-2: EC2 instances
- ...in ap-southeast-2: Elastic IP addresses
- ...in us-west-2: EC2 instances
- ...in us-west-2: Elastic IP addresses
- ...in us-west-1: EC2 instances
- ...in us-west-1: Elastic IP addresses
- ...in eu-central-1: EC2 instances
- ...in eu-central-1: Elastic IP addresses
- ...in sa-east-1: EC2 instances
- ...in sa-east-1: Elastic IP addresses
-
-My test environment has one elastic IP address that is not associated
-with an AWS resource, and one EC2 instance that has a non-elastic public IP.
-Executing the above command results in the creation of an
-"ip-ranges-nccgroup.json" file that has the following contents:
-
- {
- "createDate": "2015-11-16-22-49-27",
- "prefixes": [
- {
- "instance_id": "i-11223344",
- "ip_prefix": "1.1.1.1",
- "is_elastic": false,
- "name": "Test EC2 instance",
- "region": "us-west-2"
- },
- {
- "instance_id": null,
- "ip_prefix": "2.2.2.2",
- "is_elastic": true,
- "name": null,
- "region": "us-west-2"
- }
- ]
- }
-
-
-#### Automatically create ip-ranges from CSV files
-
-From experience, I know that many companies maintain a list of their
-public IP addresses, along with other network configuration information, in alternate formats, such as CSV. In
-order to help with the conversion, the tool supports reading CIDR information
-from CSV files. The tool was designed to be flexible and allow the creation of IP
-ranges from any CSV file. In this blog post, I provide two examples.
-
-This first example demonstrates how to use the tool to build a JSON file based
-on the CSV column headers. Only attributes specified on the command line will
-be copied over.
-
-Contents of test1.csv:
-
- ip_prefix, discarded_value, name
- 4.4.4.0/24, ncc group, NY office
- # This is a comment...
- 5.5.5.0/24, ncc group, Seattle office
-
-
-Command line to convert the contents of the CSV file into JSON:
-
- ./aws_recipes_create_ip_ranges.py --csv-ip-ranges test1.csv --attributes ip_prefix name --profile ncc-test1 --debug
-
-Contents of ip-ranges-ncc-test1.json:
-
- {
- "createDate": "2015-11-17-10-22-42",
- "prefixes": [
- {
- "ip_prefix": "4.4.4.0/24",
- "name": " NY office"
- },
- {
- "ip_prefix": "5.5.5.0/24",
- "name": " Seattle office"
- }
- ]
- }
-
-The second example demonstrates how to use the tool to parse a CSV file with
-custom column names and separate columns for the base IP and subnet mask. The
-"--mappings" argument determines how columns will be mapped to the JSON
-file's attributes.
-
-Contents of test2.csv
-
- Base IP, Dotted Subnet Mask, Subnet Mask, Something, Name, Something else
- 3.3.3.0, 255.255.255.0, /24, Value to discard, SF Office, Other value to discard
-
-Command line to convert the contents of the CSV file into JSON:
-
- ./aws_recipes_create_ip_ranges.py --csv-ip-ranges test2.csv --attributes ip_prefix mask name --mappings 0 2 4 --profile ncc-test2 --skip-first-line --debug
-
-Contents of ip-ranges-ncc-test2.json
-
- {
- "createDate": "2015-11-17-10-07-22",
- "prefixes": [
- {
- "ip_prefix": "3.3.3.0/24",
- "name": " SF Office"
- }
- ]
- }
-
-
-#### Manually create and update ip-ranges
-
-In case CIDRs were not managed in a CSV file, the tools offers an interactive
-mode that may be leveraged to manually create a JSON ip-ranges file. The
-following snippet illustrates how to use the tool to interactively create new
-ip-ranges JSON files:
-
- $ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name
-
- Add a new IP prefix to the ip ranges (y/n)?
- y
- Enter the new IP prefix:
- 5.5.5.0/24
- You entered "5.5.5.0/24". Is that correct (y/n)?
- y
- Enter the 'name' value:
- San Francisco
- You entered "San Francisco". Is that correct (y/n)?
- y
- Add a new IP prefix to the ip ranges (y/n)?
- y
- Enter the new IP prefix:
- 6.6.6.6/32
- You entered "6.6.6.6/32". Is that correct (y/n)?
- y
- Enter the 'name' value:
- San Francisco
- You entered "San Francisco". Is that correct (y/n)?
- y
- Add a new IP prefix to the ip ranges (y/n)?
- n
-
-Contents of ip-ranges-ncc-offices.json:
-
- {
- "createDate": "2015-11-16-22-44-38",
- "prefixes": [
- {
- "ip_prefix": "5.5.5.0/24",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "6.6.6.6/32",
- "name": "San Francisco"
- }
- ]
- }
-
-The tool can also automatically add new CIDRs to existing ip-ranges files:
-
- $ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name --debug
-
- Loading existing IP ranges from ip-ranges-ncc-offices.json
- Add a new IP prefix to the ip ranges (y/n)?
- y
- Enter the new IP prefix:
- 7.7.7.7/32
- You entered "7.7.7.7/32". Is that correct (y/n)?
- y
- Enter the 'name' value:
- Seattle
- You entered "Seattle". Is that correct (y/n)?
- y
- Add a new IP prefix to the ip ranges (y/n)?
- n
- File 'ip-ranges-ncc-offices.json' already exists. Do you want to overwrite it (y/n)?
- y
-
- $ cat ip-ranges-ncc-offices.json
- {
- "createDate": "2015-11-16-22-44-38",
- "prefixes": [
- {
- "ip_prefix": "5.5.5.0/24",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "6.6.6.6/32",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "7.7.7.7/32",
- "name": "Seattle"
- }
- ]
- }
-
-### Conclusion
-
-This addition to Scout2 provides AWS account administrators and auditors with
-an improved insight into their environment. Usage of this feature should result
-in further hardened security groups because detection of unknown whitelisted
-CIDRs and understanding of existing rules is significantly easier.
-
-I am currently working on a major rework of Scout2's reporting engine,
-which will further improve reporting and allow creation of new alerts when an
-unknown CIDR is whitelisted.
diff --git a/_posts/2016-08-08-blackhat_slides.markdown b/_posts/2016-08-08-blackhat_slides.markdown
deleted file mode 100644
index d63c14a..0000000
--- a/_posts/2016-08-08-blackhat_slides.markdown
+++ /dev/null
@@ -1,30 +0,0 @@
----
-layout: post
-title: "Post Black Hat US 2016 blog post"
-date: 2016-08-08 23:28
-post_author: Loïc Simon
-categories: AWS
----
-
-Last Tuesday (August 3rd), I presented "Access Keys Will Kill You Before You
-Kill The Password" at Black Hat US 2016. The summary is on the Black
-Hat website and the updated slide deck is available Here.
-This presentation aimed at highlighting risks associated with usage of AWS API
-access keys in environments that do not enforce MFA-protected API access, and
-documented strategies and IAM policies to help address these risks.
-
-On Wednesday (August 4th), I presented Scout2 at Black Hat Arsenal. During two
-hours, I had the opportunity to demo Scout2 and meet users of the tool who
-shared valuable feedback with me. I look forward to implementing some of the
-features discussed during this event, including adding support for ECS and
-finishing the new rules generator.
-
-As a reminder, Scout2 is available on Github, feedback is appreciated,
-and feature requests and pull requests are welcome. The Scout2 documentation is
-available at https://nccgroup.github.io/Scout2.
-
diff --git a/_site/feed.xml b/_site/feed.xml
deleted file mode 100644
index 627e769..0000000
--- a/_site/feed.xml
+++ /dev/null
@@ -1,1084 +0,0 @@
-
-
-
- l01cd3v.github.io
-
- http://l01cd3v.github.io
-
-
-
- Post Black Hat US 2016 blog post
- <p>Last Tuesday (August 3rd), I presented "Access Keys Will Kill You Before You
-Kill The Password" at Black Hat US 2016. The summary is on the <a
-target="_blank"
-href="https://www.blackhat.com/us-16/briefings.html#access-keys-will-kill-you-before-you-kill-the-password">Black
-Hat website</a> and the updated slide deck is available <a
-href="slides/us-16-Simon-Access-Keys-Will-Kill-You-Before-You-Kill-The-Password.pdf">Here</a>.
-This presentation aimed at highlighting risks associated with usage of AWS API
-access keys in environments that do not enforce MFA-protected API access, and
-documented strategies and IAM policies to help address these risks.</p>
-
-<p>On Wednesday (August 4th), I presented Scout2 at Black Hat Arsenal. During two
-hours, I had the opportunity to demo Scout2 and meet users of the tool who
-shared valuable feedback with me. I look forward to implementing some of the
-features discussed during this event, including adding support for ECS and
-finishing the new rules generator.</p>
-
-<p>As a reminder, Scout2 is available on <a target="_blank"
-href="https://github.com/nccgroup/Scout2">Github</a>, feedback is appreciated,
-and feature requests and pull requests are welcome. The Scout2 documentation is
-available at <a target="_blank"
-href="https://nccgroup.github.io/Scout2">https://nccgroup.github.io/Scout2</a>.</p>
-
- Mon, 08 Aug 2016 23:28:00 -0700
- http://l01cd3v.github.io/aws/2016/08/08/blackhat_slides.html
- http://l01cd3v.github.io/aws/2016/08/08/blackhat_slides.html
-
-
-
- Efficient review of AWS security groups' CIDR grants
- <p>A significant challenge for companies using the cloud lies in ensuring that
-their firewall rules follow the principle of least privilege. It is
-extremely common nowadays to delegate management of security groups to developers, for
-both production and test environments. This means that security groups and
-their associated rules are managed by a much larger number of employees than
-what used to be the case in non-cloud environments, where a unique, smaller
-team was in charge of managing all firewall rules. Due to the more dynamic
-nature of cloud-based infrastructures, companies should review their cloud
-environment's firewall rules on a more frequent basis than for non cloud-based
-systems. Unfortunately, this is a difficult exercise due to the large number of
-<a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing">CIDRs</a> that may be whitelisted in a given AWS account. Keeping track of all
-known CIDRs and what hosts or networks they represent is not easy for
-employees, and is almost impossible for external auditors who must perform the
-review within a limited timeframe.</p>
-
-<p>In this post, I will document how this issue can be addressed using the
-<a href="https://github.com/iSECPartners/AWS-recipes">AWS-Recipes</a> tools and
-<a href="https://github.com/iSECPartners/Scout2">Scout2</a>.</p>
-
-<h3>Feed custom ip-ranges files to Scout2</h3>
-
-<p>Today, I am excited to announce that Scout2 accepts JSON files that
-contain known CIDRs along with arbitrary metadata such as the host or network
-they represent. When provided with such files, Scout2's report displays the
-"friendly name" of each known CIDR that is whitelisted in security group rules.
-This means that, instead of reviewing a list of obscure IP ranges, users of
-Scout2 may now rely on the name associated with each CIDR.</p>
-
-<p>In order to use this new feature, Scout2 should be run with the following
-arguments:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">./Scout2.py --profile nccgroup --ip-ranges ip-ranges-nccgroup.json ip-ranges-ncc-offices.json --ip-ranges-key-name name
-</code></pre></div>
-<p>In the above command line, Scout2 receives two ip-ranges JSON files via the
-"--ip-ranges" argument:</p>
-
-<ul>
-<li>ip-ranges-nccgroup.json, which contains the public IP addresses in the AWS IP space in use</li>
-<li>ip-ranges-ncc-offices.json, which contains the public IP addresses of several offices</li>
-</ul>
-
-<p>Furthermore, the "--ip-ranges-key-name" argument indicates which JSON field to
-display as the "friendly name".</p>
-
-<p>The following screenshot illustrates that, in the Scout2 report, the name of
-each known CIDR is displayed. When an IP which belongs to a known CIDR is
-whitelisted, the name of the corresponding CIDR is used. In this example,
-5.5.5.42/32 belongs to the 5.5.5.0/24 CIDR, which is associated with the "San
-Francisco" office. An "Unknown CIDR" value is displayed when an unknown value
-is whitelisted.</p>
-
-<p><img src="/images/aws/awsscout2-ec2-cidr-friendlyname.png" alt="Screenshot: Security group rules display the name of each known CIDRs"></p>
-
-<p>The next section of this blog post documents how users can create and manage
-these ip-ranges JSON files.</p>
-
-<h3>Manage known CIDRs with aws_recipes_create_ip_ranges.py</h3>
-
-<p>With AWS releasing their public IP address ranges, I decided to create a tool
-that allows creation and management of arbitrary IP address ranges using the
-same JSON format. The tool is released on GitHub at
-<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_create_ip_ranges.py">https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_create_ip_ranges.py</a>
-and may be used in several scenarios:</p>
-
-<ul>
-<li>Automatically create ip-ranges files based on public IP addresses in AWS (Elastic IPs and EC2 instances)</li>
-<li>Automatically create ip-ranges files based on IP addresses documented in a CSV file</li>
-<li>Manually create and manage ip-ranges files</li>
-</ul>
-
-<p>Each of these use cases is detailed in an example below, with detailed input,
-commands, and output contents.</p>
-
-<p><strong><em>Note:</em></strong> In the commands below, the "--debug" argument is used to
-output pretty-printed JSON, for documentation purposes.</p>
-
-<h4>Automatically create ip-ranges based on public IP addresses in an AWS account</h4>
-
-<p>First, this tool may be used to create an ip-ranges file that contains an AWS
-account's elastic IP addresses and EC2 instances' public IP addresses. By doing
-so, AWS users will be able to maintain a list of public IP addresses in the AWS
-IP space that are associated with their resources. Assuming that AWS
-credentials are configured under the "nccgroup" profile name, the command
-below may be used:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --profile nccgroup --debug
-
-Fetching public IP information for the 'nccgroup' environment...
-...in us-east-1: EC2 instances
-...in us-east-1: Elastic IP addresses
-...in ap-northeast-1: EC2 instances
-...in ap-northeast-1: Elastic IP addresses
-...in eu-west-1: EC2 instances
-...in eu-west-1: Elastic IP addresses
-...in ap-southeast-1: EC2 instances
-...in ap-southeast-1: Elastic IP addresses
-...in ap-southeast-2: EC2 instances
-...in ap-southeast-2: Elastic IP addresses
-...in us-west-2: EC2 instances
-...in us-west-2: Elastic IP addresses
-...in us-west-1: EC2 instances
-...in us-west-1: Elastic IP addresses
-...in eu-central-1: EC2 instances
-...in eu-central-1: Elastic IP addresses
-...in sa-east-1: EC2 instances
-...in sa-east-1: Elastic IP addresses
-</code></pre></div>
-<p>My test environment has one elastic IP address that is not associated
-with an AWS resource, and one EC2 instance that has a non-elastic public IP.
-Executing the above command results in the creation of an
-"ip-ranges-nccgroup.json" file that has the following contents:</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-16-22-49-27"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"instance_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"i-11223344"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.1.1.1"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"is_elastic"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Test EC2 instance"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"region"</span><span class="p">:</span><span class="w"> </span><span class="s2">"us-west-2"</span><span class="w">
- </span><span class="p">},</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"instance_id"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.2.2.2"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"is_elastic"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
- </span><span class="nt">"region"</span><span class="p">:</span><span class="w"> </span><span class="s2">"us-west-2"</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<h4>Automatically create ip-ranges from CSV files</h4>
-
-<p>From experience, I know that many companies maintain a list of their
-public IP addresses, along with other network configuration information, in alternate formats, such as CSV. In
-order to help with the conversion, the tool supports reading CIDR information
-from CSV files. The tool was designed to be flexible and allow the creation of IP
-ranges from any CSV file. In this blog post, I provide two examples.</p>
-
-<p>This first example demonstrates how to use the tool to build a JSON file based
-on the CSV column headers. Only attributes specified on the command line will
-be copied over.</p>
-
-<p>Contents of test1.csv:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">ip_prefix, discarded_value, name
-4.4.4.0/24, ncc group, NY office
-# This is a comment...
-5.5.5.0/24, ncc group, Seattle office
-</code></pre></div>
-<p>Command line to convert the contents of the CSV file into JSON:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">./aws_recipes_create_ip_ranges.py --csv-ip-ranges test1.csv --attributes ip_prefix name --profile ncc-test1 --debug
-</code></pre></div>
-<p>Contents of ip-ranges-ncc-test1.json:</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-17-10-22-42"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4.4.4.0/24"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" NY office"</span><span class="w">
- </span><span class="p">},</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5.5.5.0/24"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" Seattle office"</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<p>The second example demonstrates how to use the tool to parse a CSV file with
-custom column names and separate columns for the base IP and subnet mask. The
-"--mappings" argument determines how columns will be mapped to the JSON
-file's attributes.</p>
-
-<p>Contents of test2.csv</p>
-<div class="highlight"><pre><code class="language-" data-lang="">Base IP, Dotted Subnet Mask, Subnet Mask, Something, Name, Something else
-3.3.3.0, 255.255.255.0, /24, Value to discard, SF Office, Other value to discard
-</code></pre></div>
-<p>Command line to convert the contents of the CSV file into JSON:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">./aws_recipes_create_ip_ranges.py --csv-ip-ranges test2.csv --attributes ip_prefix mask name --mappings 0 2 4 --profile ncc-test2 --skip-first-line --debug
-</code></pre></div>
-<p>Contents of ip-ranges-ncc-test2.json</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-17-10-07-22"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"3.3.3.0/24"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" SF Office"</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<h4>Manually create and update ip-ranges</h4>
-
-<p>In case CIDRs were not managed in a CSV file, the tools offers an interactive
-mode that may be leveraged to manually create a JSON ip-ranges file. The
-following snippet illustrates how to use the tool to interactively create new
-ip-ranges JSON files:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name
-
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-5.5.5.0/24
-You entered "5.5.5.0/24". Is that correct (y/n)?
-y
-Enter the 'name' value:
-San Francisco
-You entered "San Francisco". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-6.6.6.6/32
-You entered "6.6.6.6/32". Is that correct (y/n)?
-y
-Enter the 'name' value:
-San Francisco
-You entered "San Francisco". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-n
-</code></pre></div>
-<p>Contents of ip-ranges-ncc-offices.json:</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-16-22-44-38"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5.5.5.0/24"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"San Francisco"</span><span class="w">
- </span><span class="p">},</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"6.6.6.6/32"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"San Francisco"</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<p>The tool can also automatically add new CIDRs to existing ip-ranges files:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name --debug
-
-Loading existing IP ranges from ip-ranges-ncc-offices.json
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-7.7.7.7/32
-You entered "7.7.7.7/32". Is that correct (y/n)?
-y
-Enter the 'name' value:
-Seattle
-You entered "Seattle". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-n
-File 'ip-ranges-ncc-offices.json' already exists. Do you want to overwrite it (y/n)?
-y
-
-$ cat ip-ranges-ncc-offices.json
-{
- "createDate": "2015-11-16-22-44-38",
- "prefixes": [
- {
- "ip_prefix": "5.5.5.0/24",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "6.6.6.6/32",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "7.7.7.7/32",
- "name": "Seattle"
- }
- ]
-}
-</code></pre></div>
-<h3>Conclusion</h3>
-
-<p>This addition to Scout2 provides AWS account administrators and auditors with
-an improved insight into their environment. Usage of this feature should result
-in further hardened security groups because detection of unknown whitelisted
-CIDRs and understanding of existing rules is significantly easier.</p>
-
-<p>I am currently working on a major rework of Scout2's reporting engine,
-which will further improve reporting and allow creation of new alerts when an
-unknown CIDR is whitelisted.</p>
-
- Tue, 17 Nov 2015 08:00:00 -0800
- http://l01cd3v.github.io/aws/2015/11/17/ip_ranges_management.html
- http://l01cd3v.github.io/aws/2015/11/17/ip_ranges_management.html
-
-
-
- Redshift support added in Scout2
- <p>Today, I am excited to announce that support for Redshift was added in
-Scout2. By default, Scout2 will fetch information about your Redshift clusters,
-cluster parameter groups, and cluster security groups if you still use
-EC2-Classic. At this stage, Scout2 comes with six Redshift security rules that
-are enabled by default:</p>
-
-<ul>
-<li>Clusters
-
-<ul>
-<li>Check whether version upgrade is enabled</li>
-<li>Check whether the cluster is publicly accessible</li>
-<li>Check whether database encryption is enabled</li>
-</ul></li>
-<li>Cluster parameter groups
-
-<ul>
-<li>Check whether SSL/TLS is required to access the database</li>
-<li>Check whether user activity logging is enabled</li>
-</ul></li>
-<li>Cluster security groups (EC2-classic)
-
-<ul>
-<li>Check whether the security group allows access to all IP addresses (0.0.0.0/0)</li>
-</ul></li>
-</ul>
-
-<p>Scout2 was first released over a year and a half ago, and proved to be extremely
-helpful when performing AWS configuration reviews. While
-Scout2's initial release only supported three services (IAM, EC2, and S3) and
-included thirteen security checks, the tool rapidly grew to add support for RDS
-and CloudTrail. Furthermore, the tool now offers over fifty tests throughout
-these five supported services. I hope that support for Redshift will bring
-value to users of Scout2, and welcome feature requests, bug reports, and
-recommendations on Github at
-<a href="https://github.com/iSECPartners/Scout2/issues">https://github.com/iSECPartners/Scout2/issues</a>.</p>
-
- Thu, 06 Aug 2015 08:39:00 -0700
- http://l01cd3v.github.io/aws/2015/08/06/scout2_supports_redshift.html
- http://l01cd3v.github.io/aws/2015/08/06/scout2_supports_redshift.html
-
-
-
- Introducing opinel: Scout2's favorite tool
- <p>With boto3 being stable and generally available<sup><a href="https://aws.amazon.com/about-aws/whats-new/2015/06/boto3-aws-sdk-for-python-version-3-is-now-generally-available">1</a></sup>, I took the opportunity
-to migrate Scout2 and AWS-recipes to boto3. As part of that migration
-effort, I decided to publish the formerly-known-as AWSUtils repository -- used
-by Scout2 and AWS-recipes -- as a python package required by these tools,
-rather than requiring users to work with Git submodules. I've also added more
-flexibility when working with MFA-protected API calls and improved versioning
-across the project.</p>
-
-<h3>opinel</h3>
-
-<p>To avoid name conflicts, I decided to rename the shared AWSUtils code to a
-less misleading name: opinel. The opinel package is published on <a href="https://pypi.python.org/pypi/opinel">PyPI</a>, and thus can
-be installed using pip and easy_install. The corresponding source code is still
-open-sourced on Github at <a href="https://github.com/iSECPartners/opinel">https://github.com/iSECPartners/opinel</a>.
-As a result, Scout2 and AWS-recipes have been modified to list opinel as a
-requirement, which significantly simplifies installation and management of this
-shared code.</p>
-
-<h3>Support for Python 2.7 and 3.x</h3>
-
-<p>Because boto3 supports both Python2 and Python3, I decided to make sure that
-the code built on top of that package has similar properties. As a result,
-the latest versions of Scout2 and AWS-recipes support Python 2.7 and 3.x.
-Note that opinel will <strong>NOT</strong> work with Python 2.6.</p>
-
-<h3>Modification of the MFA workflow</h3>
-
-<p>As requested by a user of AWS-recipes<sup><a href="https://github.com/iSECPartners/opinel/issues/4">2</a></sup>, I modified the workflow when
-using MFA-protected API access to no longer store the long-lived credentials
-in a separate file. As a result, the <em>.aws/credentials.no-mfa</em> file is no
-longer supported and all credentials are stored in the standard AWS credentials
-file under <em>.aws/credentials</em>. Usage of the existing tools remains unchanged,
-but the long-lived credentials are now accessible via a new profile name:
-<em>profile_name-nomfa</em>. This allows users to work with both STS and long-lived
-credentials if need be.</p>
-
-<p>If you already had configured your environment to work with MFA-protected API
-access, you will need to copy your long-lived credentials back to the
-<em>.aws/credentials</em> file. This can be done with a simple command such as the
-following:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">cat ~/.aws/credentials.no-mfa | sed -e 's/]$/-nomfa]/g' >> ~/.aws/credentials
-</code></pre></div>
-<h3>Support to use assumed-role credentials</h3>
-
-<p>With this new workflow implemented, I created a new recipe that allows
-configuration of role-credentials in the <em>.aws/credentials</em> file. When the following
-command is run, it uses the credentials associated with the <em>isecpartners</em>
-profile to request role credentials for the IAM-Scout2 role. The role
-credentials are then written in the <em>.aws/credentials</em> file in a new profile
-named <em>isecpartners-Scout2</em>, which is the profile name appended by the role
-session name.</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_assume_role.py --profile isecpartners --role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/IAM-Scout2 --role-session-name Scout2
-</code></pre></div>
-<p>Users can then use their favorite tools that support profiles. For example,
-Scout2 could be run with the following command line:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./Scout2.py --profile isecpartners-Scout2
-</code></pre></div>
-<p>Note that this recipe supports MFA if the assumed role requires it:</p>
-
-<ul>
-<li>If you never configured your environment to work with MFA, you can provide your MFA serial number (ARN) and current token code as arguments.</li>
-<li>If you already configured your environment to work with MFA and stored your MFA serial in the <em>.aws/credentials</em> file, you just need to pass your token code as an additional argument.</li>
-<li>Finally, if you already initiated an STS session, you do not need to provide a new token code and can run the command as above.</li>
-</ul>
-
-<h3>Conclusion</h3>
-
-<p>With the release of opinel, I hope to simplify distribution and management of
-the code shared between Scout2 and AWS-recipes. Additionally, I
-significantly modified the workflow and credentials storage when working with
-MFA-protected API calls, which allows users to use both their long-lived and STS
-credentials.</p>
-
- Mon, 03 Aug 2015 11:08:00 -0700
- http://l01cd3v.github.io/aws/2015/08/03/boto3_opinel_scout_recipes.html
- http://l01cd3v.github.io/aws/2015/08/03/boto3_opinel_scout_recipes.html
-
-
-
- IAM user management strategy (part 2)
- <p>The previous <a href="/aws/2015/02/24/iam_user_management.html">IAM user management strategy</a> post discussed how
-usage of IAM groups enables AWS administrators to consistently grant privileges
-and enforce a number of security rules (such as MFA-protected API access). This
-blog post will build on this idea by introducing category groups and
-documenting new tools to improve IAM user management.</p>
-
-<h3>Categorize your IAM users</h3>
-
-<p>For a variety of reasons, applying a single set of security rules to all IAM
-users is not always practical. For example, because many applications running
-in AWS predate IAM roles, numerous environments still rely on the existence of
-headless IAM users. Additionally, third parties may be granted access to an AWS
-account for a number of reasons but may not be able to comply with the same set
-of security rules that employees follow. For this reason, NCC recommends using
-category groups to sort IAM users and reliably enforce appropriate security
-measures. For example, one group for all human users and a second for all headless users may be
-created: MFA-protected API access and password management are not relevant for
-headless users. Furthermore, human users may be categorized into several groups
-such as employees and contractors: API access can be restricted to the
-corporate IP range for employees but might not be achievable for contractors.</p>
-
-<p><em>Note 1:</em> The set of category groups should define all types of IAM users that
-may exist in your AWS account and each IAM user should belong to one -- and
-only one -- category group (they may belong to other groups though).</p>
-
-<p><em>Note 2:</em> The common group and category groups should be used to enable enforcing
-security in one's AWS environment. Policies attached to these groups should be
-carefully reviewed and grant the minimum set of privileges necessary for this
-type of IAM user (<em>e.g.</em> credential management for humans).</p>
-
-<h3>Example of category groups</h3>
-
-<p>The rest of this article describes a number of tools developed and used by
-NCC to help implement this IAM user management strategy. These tools can be found
-in the <a href="https://github.com/iSECPartners/AWS-recipes">AWS-Recipes</a> repository. We will
-use our test AWS environment as an example, in which we use three category groups in
-addition to the <em>AllUsers</em> common group:</p>
-
-<ol>
-<li><em>AllHumans</em>, the group all employees must belong to.</li>
-<li><em>AllHeadlessUsers</em>, the group all headless IAM users must belong to.</li>
-<li><em>AllMisconfiguredUsers</em>, a placeholder for sample misconfigured users.</li>
-</ol>
-
-<p>We also have an IAM user naming convention that requires usernames to match the
-following schema:</p>
-
-<ol>
-<li>Employees: firstname initial appended with lastname</li>
-<li>Headless user: name of the service prefixed with <em>HeadlessUser-</em></li>
-<li>Misconfigured: description of the misconfiguration prefixed with <em>MisconfiguredUser-</em></li>
-</ol>
-
-<p>Based on these rules, we created a configuration file stored under
-<em>.aws/recipes/isecpartners.json</em>, with <em>isecpartners</em> matching the profile's
-name. If you do not use profiles, the configuration will be under
-<em>.aws/recipes/default.json</em>.</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"common_groups"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"AllUsers"</span><span class="w"> </span><span class="p">],</span><span class="w">
- </span><span class="nt">"category_groups"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="s2">"AllHumanUsers"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"AllHeadlessUsers"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"AllMisconfiguredUsers"</span><span class="w">
- </span><span class="p">],</span><span class="w">
- </span><span class="nt">"category_regex"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="s2">""</span><span class="p">,</span><span class="w">
- </span><span class="s2">"^Headless-(.*)"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"^MisconfiguredUser-(.*)"</span><span class="w">
- </span><span class="p">],</span><span class="w">
- </span><span class="nt">"profile_name"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"isecpartners"</span><span class="w"> </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<p>This configuration file declares the name of the common IAM group and two lists
-related to the categorization of IAM users:</p>
-
-<ol>
-<li>A list of category groups.</li>
-<li>A list of regular expressions matching our naming convention.</li>
-</ol>
-
-<p><em>Note 1:</em> If you do not have a naming convention in place to distinguish the
-type of user, remove the <em>category_regex</em> attribute from your configuration
-file.</p>
-
-<p><em>Note 2:</em> If a regular expression is only applicable to a subset of category
-groups, you must ensure that both lists have the same length and use an empty
-string for groups that cannot be automatically associated (see the
-<em>AllHumanUsers</em> group in our example).</p>
-
-<p><em>Note 3:</em> Use of a configuration file is not necessary as all values may be
-passed as command line arguments. If a configuration file exists and a value is
-passed as an argument, the value passed via the command line will be used.</p>
-
-<h3>Create your default groups with <em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_default_groups.py">aws_iam_create_default_groups.py</a></em></h3>
-
-<p>The purpose of this tool is to create IAM groups whose name matches the common
-and category groups specified in the above configuration file. Running the
-following command results in four new groups being created if they did not
-already exist.</p>
-<div class="highlight"><pre><code class="language-" data-lang="">./aws_iam_create_default_groups.py --profile isecpartners
-</code></pre></div>
-<h3>(Automatically) sort IAM users with <em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_sort_users.py">aws_iam_sort_users.py</a>.</em></h3>
-
-<p>This tool iterates through all IAM users and attempts to automatically detect
-the IAM groups each user should belong to. For convenience, we recommend adding
-the following to your AWS recipes configuration files:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">"aws_sort_users.py": {
- "create_groups": false,
-},
-"force_common_group": true
-</code></pre></div>
-<p>This specifies default values for additional arguments to be set when running
-<em>aws_iam_sort_users.py</em>. Specifically, with these values, running this tool
-will automatically add all IAM users to the common group <em>AllUsers</em> and will
-not attempt to create the default groups (not necessary as we already did
-this). Additionally, this tool checks that each IAM user belongs to one of the
-category groups. If this is not the case and the username matches a regular
-expression, the user is automatically added to the matching category group. Otherwise, a
-multi-choice prompt appears to allow manual selection of the appropriate
-category group.</p>
-
-<h3>Additional advantages of configuration files</h3>
-
-<p>Besides helping with simplification of these tools' usage, this new AWS-recipe
-configuration file can be used across tools, allowing for more consistent
-rule enforcement. For example, the
-<em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_user.py">aws_iam_create_user.py</a>.</em>
-tool uses this configuration file and applies the same business logic to add
-users to the common group and appropriate category group at user creation time. In
-our test environment, for example, running the following command automatically
-added the new user to the <em>MisconfiguredUser</em> group:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_iam_create_user.py --profile isecpartners --users MisconfiguredUser-BlogPostExample
-Creating user MisconfiguredUser-BlogPostExample...
-Save unencrypted value (y/n)? y
-User 'MisconfiguredUser-BlogPostExample' does not belong to the mandatory common group 'AllUsers'. Do you want to remediate this now (y/n)? y
-User 'MisconfiguredUser-BlogPostExample' does not belong to any of the category group (AllHumanUsers, AllHeadlessUsers, AllMisconfiguredUsers). Automatically adding...
-Enabling MFA for user MisconfiguredUser-BlogPostExample...
-</code></pre></div>
-<h3>Conclusion</h3>
-
-<p>While efficient and reliable management of IAM users can be challenging, using
-the right strategy and tools significantly simplifies this process. Creation
-and use of a naming convention for IAM users enables
-automated user management and enforcement of security rules.</p>
-
- Tue, 09 Jun 2015 09:20:00 -0700
- http://l01cd3v.github.io/aws/2015/06/09/iam_user_management_2.html
- http://l01cd3v.github.io/aws/2015/06/09/iam_user_management_2.html
-
-
-
- Work daily with enforced MFA-protected API access
- <h3>AWS Security Token Service</h3>
-
-<p>The AWS Security Token Service (STS) is the gateway used to create sessions
-when MFA-protected API access is enabled. This service allows IAM users to
-retrieve short-lived credentials (<em>i.e</em> access key ID, secret access key, and
-session token) in exchange for their long-lived credentials (<em>i.e.</em> AWS access
-key ID and secret key) and their current authentication code. When enforcing
-MFA-protected API access, as recommended in the previous <a href="/aws/2015/04/02/use_and_enforce_mfa.html">Use and enforce
-Multi-Factor
-Authentication</a> post,
-IAM users must use these short-lived credentials to access other AWS services.</p>
-
-<h3>Challenges with MFA-protected API access</h3>
-
-<p>When MFA-protected API access is enforced, managing AWS access keys becomes
-challenging because configuration files that contain these credentials must be
-updated regularly. Users must also ensure that they do not lose their
-long-lived credentials when modifying the configuration files to write their
-short-lived credentials. In order to help with this workflow, iSEC wrote and
-released several simple tools in the
-<a href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a> repository.</p>
-
-<p>The collection of tools that we will discussed below uses the "<a
-target="_blank"
-href="https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs">new
-and standardized way to manage credentials in the AWS SDKs</a>", meaning that
-SDKs are expecting to read credentials from the <em>.aws/credentials</em> file under
-the user's home or profile directory.</p>
-
-<h3>aws_recipes_configure_iam.py</h3>
-
-<p>The
-<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_configure_iam.py">aws_recipes_configure_iam.py</a>
-tool allows users to configure and store their long-lived credentials in a new,
-non-standard, <em>.aws/credentials.no-mfa</em> file. In addition to prompting for the
-AWS access key ID and secret key, this tool also prompts for the MFA device
-serial number because this information must be provided when making calls to
-the STS API. Similar to the AWS CLI and SDKs, it supports profile names. The
-following code snippet is an example of calling this tool to configure a new
-profile called <em>isecpartners</em>:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_configure_iam.py --profile isecpartners
-AWS Access Key ID: AWS_KEY_ID
-AWS Secret Access Key: AWS_SECRET_KEY
-AWS MFA serial: arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
-</code></pre></div>
-<p>When looking at the <em>.aws</em> folder, we can see that a <em>credentials.no-mfa</em> file
-exists and that it contains the credentials that were just entered:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ls -l ~/.aws
-total 4
--rw-r--r-- 1 loic loic 93 Apr 3 14:00 credentials.no-mfa
-$ cat ~/.aws/credentials.no-mfa
-[isecpartners]
-aws_access_key_id = AWS_KEY_ID
-aws_secret_access_key = AWS_SECRET_KEY
-aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
-</code></pre></div>
-<p>Now that long-lived credentials are configured, we can use the next tool to
-call the AWS STS API and request short-lived credentials that will be used
-to access other AWS services.</p>
-
-<h3>aws_recipes_init_sts_session.py</h3>
-
-<p>The
-<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py">aws_recipes_init_sts_session.py</a>
-tool reads long-lived credentials configured in the .aws/credentials.no-mfa
-file, prompts users for their MFA code, and retrieves STS credentials (AWS
-access key ID, AWS secret key, and session token). The short-lived credentials
-are then saved under the standardized <em>.aws/credentials</em> file to be accessible
-to the AWS CLI and other tools built with the AWS SDKs. The following code
-snippet demonstrates calling this tool to request an STS session token:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_init_sts_session.py --profile isecpartners
-Enter your MFA code: 123456
-Successfully configured the session token for profile 'isecpartners'.
-</code></pre></div>
-<p>When looking at the <em>.aws</em> folder, we can see that a standard <em>credentials</em>
-file now exists as well and that it contains the short-lived credentials:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">$ ls -l ~/.aws
-total 8
--rw-r--r-- 1 loic loic 576 Apr 3 14:14 credentials
--rw-r--r-- 1 loic loic 179 Apr 3 14:00 credentials.no-mfa
-$ cat ~/.aws/credentials
-[isecpartners]
-aws_access_key_id = STS_KEY_ID
-aws_secret_access_key = STS_SECRET_KEY
-aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
-aws_session_token = AWS//////////SESSION_TOKEN
-</code></pre></div>
-<p>Now that the short-lived credentials are configured, we can use the AWS CLI or
-other tools built with the AWS SDKs that read credentials from this standard
-location. When the STS session expires, users just need to re-run the
-<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py">aws_recipes_init_sts_session.py</a>
-tool and the standard <em>credentials</em> file will be updated with new valid
-short-lived credentials.</p>
-
-<h3>Conclusion</h3>
-
-<p>By using this pair of tools to manage their AWS access keys, IAM users can
-easily use the AWS CLI and other tools built with various AWS SDKs in
-environments that have been secured and enforce MFA-protected API access.</p>
-
- Fri, 03 Apr 2015 14:10:00 -0700
- http://l01cd3v.github.io/aws/2015/04/03/session_management_tools.html
- http://l01cd3v.github.io/aws/2015/04/03/session_management_tools.html
-
-
-
- Use and enforce Multi-Factor Authentication
- <h3>What is Multi-Factor Authentication?</h3>
-
-<p>When enabled, Multi-Factor Authentication (MFA) provides strong
-defense-in-depth against compromises of credentials. MFA-enabled users have a
-device that periodically generates a new authentication code (<em>i.e.</em> one-time
-password); they need to enter the current authentication code along with their
-static credentials (<em>i.e.</em> username and password) in order to successfully
-authenticate. In addition to supporting MFA when accessing the web console
-(<em>i.e.</em> password-based authentication), AWS also offers MFA-protected API
-access for users who work with AWS access keys. Through the Security Token
-Service (STS), IAM users can request temporary credentials in exchange for
-their long-lived credentials (<em>i.e.</em> AWS access key ID and secret key) and
-their current authentication code.</p>
-
-<h3>Why should one use and enforce MFA?</h3>
-
-<p>For companies deploying their application in the cloud, a breach that results
-in unauthorized access to the management console — or API — is the
-worst-case scenario. While a number of AWS administrators have realized the
-importance of enabling MFA when they access the web console, a limited number
-of them enforce MFA-protected API access. This represents a huge gap in one's
-security posture because AWS access keys do not come with as many security
-features as passwords do:</p>
-
-<ul>
-<li>AWS administrators can enforce password expiration; this is currently not
-possible for AWS access keys.</li>
-<li>While it is probably safe to assume that most AWS administrators do not store
-their password in plaintext, most of them use AWS access keys. By design, these
-keys are meant to be stored in plaintext files that are accessed by tools built
-with the various AWS SDKs.</li>
-<li>A lost password is a forgotten password; a lost key is a key stored in a lost
-file, which may be on an unencrypted storage device (e.g. hard drive or USB Flash
-drive).</li>
-</ul>
-
-<p>Because AWS access keys are long-lived credentials that are stored in plaintext
-files, they are more susceptible to compromise than passwords. It is therefore
-necessary to enable MFA when the AWS API is accessed using these keys and not
-only when users sign in using their passwords.</p>
-
-<h3>How can one enforce MFA?</h3>
-
-<p>Unfortunately, at time of writing, AWS does not offer an option to enforce
-MFA-protected API access via a global setting. Therefore, AWS account
-administrators must carefully manage their IAM users and develop a strategy to
-reliably achieve this. In order to enforce MFA-protected API access, iSEC
-recommends the following:</p>
-
-<ol>
-<li>Create a common IAM group that all IAM users belong to, as discussed in the previous <a href="/aws/2015/02/24/iam_user_management.html">IAM user management strategy</a> post.</li>
-<li>Add the following policy (also available on <a href="https://github.com/iSECPartners/AWS-recipes/blob/master/IAM-Policies/EnforceMFA-8HourSession.json">Github</a>) to enforce MFA for all users who belong to this group.</li>
-</ol>
-
-<p>This policy will enforce MFA regardless of how the IAM user authenticated with
-AWS; it will be effective whether they use password-based or key-based
-authentication.</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Deny"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Condition"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
- </span><span class="nt">"Null"</span><span class="p">:{</span><span class="nt">"aws:MultiFactorAuthAge"</span><span class="p">:</span><span class="s2">"true"</span><span class="p">}</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">},</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Deny"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Condition"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
- </span><span class="nt">"NumericGreaterThan"</span><span class="p">:{</span><span class="nt">"aws:MultiFactorAuthAge"</span><span class="p">:</span><span class="s2">"28800"</span><span class="p">}</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<p>The first statement in the above policy denies all actions if the
-<em>aws:MultiFactorAuthAge</em> key is not present; this key only exists if MFA is
-used [1].</p>
-
-<p>The second statement verifies that the validation of the MFA code was performed
-less than eight hours ago. Temporary credentials may be valid for a duration
-between fifteen minutes and thirty-six hours [2]. iSEC recommends requiring
-users to initiate a new session at least once a day.</p>
-
-<p><strong><em>Note:</em></strong> An "explicit deny" means that, regardless of other policies granted
-to a user, this deny rule will prevail. More information about the IAM policy
-evaluation logic can be found in the AWS documentation at <a
-target="_blank"
-href="http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html">http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html</a>.</p>
-
-<h3>Use AWS Scout2 to detect users without MFA</h3>
-
-<p>The default ruleset used by <a href="https://github.com/iSECPartners/Scout2">AWS Scout2</a> includes a rule that checks for IAM users who have password-based authentication enabled but do not have an MFA device configured. If Scout2 detects IAM users with password-based authentication enabled and no MFA device, it will document a "Lack of MFA" security risk in the IAM menu dropdown, as illustrated in the below screenshot.</p>
-
-<p><img src="/images/aws/awsscout2-user-nomfa-1.png" alt="Screenshot: IAM menu dropdown with a "Lack of MFA" security risk"></p>
-
-<p>When clicked, this "Lack of MFA" link filters the list of IAM users to display
-those who have password-based authentication enabled but no MFA device
-configured. The red "No" following "Multi-Factor enabled" indicates a danger
-tied to that particular IAM user.</p>
-
-<p><img src="/images/aws/awsscout2-user-nomfa-2.png" alt="Screenshot: Red "No" indicating that this IAM user may access the web console without MFA"></p>
-
-<h3>How can one use MFA with command line tools?</h3>
-
-<p>Users of the AWS CLI (and other command line tools) have several methods to
-configure their credentials, such as environment variables, configuration
-files, or command line arguments. However, updating these settings on a daily
-basis when MFA-protected API access is enabled is inconvenient. To help
-facilitate this work flow, iSEC has created a set of Python tools and released
-them in the <a href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a>
-repository. Further details about these tools will be published in the next
-blog post.</p>
-
-<p>Additional information about MFA with AWS is available in the AWS
-documentation at <a target="_blank"
-href="https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingMFA.html">
-https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingMFA.html</a>.</p>
-
-<h3>Conclusion</h3>
-
-<p>Enforcing Multi-Factor Authentication for all IAM users is extremely important
-in order to mitigate the risks of credentials compromise (especially the AWS
-access key ID and secret). This aspect of security is commonly overlooked and
-may result in catastrophic damages. By using a strict strategy for management
-of IAM users and the above IAM policy, AWS administrators may significantly
-reduce risks of account compromise.</p>
-
-<p>[1] <a target="_blank" href="http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_ElementDescriptions.html#AvailableKeys">http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_ElementDescriptions.html#AvailableKeys</a></p>
-
-<p>[2] <a target="_blank" href="http://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html">http://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html</a></p>
-
- Thu, 02 Apr 2015 14:10:00 -0700
- http://l01cd3v.github.io/aws/2015/04/02/use_and_enforce_mfa.html
- http://l01cd3v.github.io/aws/2015/04/02/use_and_enforce_mfa.html
-
-
-
- IAM user management strategy
- <h3>Use IAM groups</h3>
-
-<p>When granting privileges to IAM users, AWS account administrators should avoid
-use of user-specific policies. Instead, create groups whose name explicitly
-defines the members' job functions or responsibilities (<em>e.g.</em> AWS
-Administrators, Operations, Developers, Accountants), and define the
-permissions granted within group policies. Doing so will simplify the
-permissions management process as changes in group policies apply to all
-members.</p>
-
-<p>When performing AWS configuration reviews, iSEC often discovers IAM users
-whose privileges have been granted via a combination of IAM user and IAM group
-policies. It is not uncommon to see IAM users who are granted full
-administrator privileges in a redundant manner, via both user and group
-policies. Such configuration creates an avenue for configuration mistakes, as
-another administrator may believe that terminating an IAM user's membership to
-the admin group is sufficient. Therefore, banning use of IAM user policies
-will result in making one's AWS environment less error-prone.</p>
-
-<p><strong><em>Note</em></strong>: It is on purpose that iSEC recommends using IAM group names that
-reflect a job title or responsibility. IAM users who do not fit in such groups
-(<em>e.g.</em> headless users) should not exist. Instead, AWS account administrators
-should investigate use of IAM roles for EC2. Further details will be discussed
-in an upcoming blog post.</p>
-
-<h3>Create a common IAM group to apply generic policies</h3>
-
-<p>Because a number of policies must be applied to all users, iSEC recommends that
-AWS account administrators create an IAM group that all IAM users belong to.
-Doing so will allow AWS account administrators to consistently grant privileges
-and enforce a number of rules.</p>
-
-<p><strong><em>Note</em></strong>: It is important that all IAM users belong to this common IAM group
-to ensure that policies are consistently applied. Failure to do so will create
-gaps in one's AWS environment security posture.</p>
-
-<h3>Authorize IAM users to manage their credentials</h3>
-
-<p>To begin with, iSEC recommends that AWS account administrators allow all of
-their IAM users to manage their credentials, and only theirs. With all IAM
-users belonging to the common IAM group, this can be achieved by applying the
-following IAM policy to the group.</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="s2">"iam:*AccessKey*"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"iam:*Password"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"iam:*MFADevice*"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"iam:UpdateLoginProfile"</span><span class="w">
- </span><span class="p">],</span><span class="w">
- </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:iam::AWS_ACCOUNT_ID:user/${aws:username}"</span><span class="w">
- </span><span class="p">},</span><span class="w">
- </span><span class="p">{</span><span class="w">
- </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
- </span><span class="s2">"iam:CreateVirtualMFADevice"</span><span class="p">,</span><span class="w">
- </span><span class="s2">"iam:DeleteVirtualMFADevice"</span><span class="w">
- </span><span class="p">],</span><span class="w">
- </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:iam::AWS_ACCOUNT_ID:mfa/${aws:username}"</span><span class="w">
- </span><span class="p">}</span><span class="w">
- </span><span class="p">]</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<p>While the above policy is sufficient to allow users to manage their
-credentials, AWS administrators may consider the following statement as an
-addition; it allows IAM users to know what the account's password policy is.</p>
-<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
- </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"iam:GetAccountPasswordPolicy"</span><span class="p">,</span><span class="w">
- </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="w">
-</span><span class="p">}</span><span class="w">
-</span></code></pre></div>
-<h3>Use AWS Scout2 to detect user policies</h3>
-
-<p>The default ruleset used by <a href="https://github.com/iSECPartners/Scout2">AWS
-Scout2</a> includes a rule that checks for
-user policies and reports the use of user-specific IAM policies as a warning.
-Detection of user-specific IAM policies results in the IAM menu dropdown
-containing a "User policies" security risk, as illustrated in the below screenshot.</p>
-
-<p><img src="/images/aws/awsscout2-iam-user-policy-1.png" alt="Screenshot: IAM menu dropdown with a User policies security risk"></p>
-
-<p>When clicked-on, this "User policies" link filters the list of IAM users to only
-display those who have at least one user policy attached. The orange badge
-indicates a warning and the count of user policies attached to this particular
-IAM user.</p>
-
-<p><img src="/images/aws/awsscout2-iam-user-policy-2.png" alt="Screenshot: Orange badge indicating that at least one user policy is attached to that IAM user"></p>
-
-<h3>Check that all IAM users belong to the common group</h3>
-
-<p>AWS Scout2 comes with a tool — RulesGenerator.py — that allows AWS account
-administrators to generate a custom ruleset to tailor the report to their
-needs. An optional IAM rule requires all IAM users to belong to a common IAM
-group. In order to enable this rule, the following can be done:</p>
-
-<ol>
-<li>Run the rules generator with the following command line:
-<pre style="margin-left: -20px; margin-top: 10px; margin-bottom: 10px"><code>./RulesGenerator.py --ruleset_name isec --services iam</pre></code></li>
-<li>Answer "yes" to the question "Would you like to ensure that all IAM users belong to a given IAM group?"</li>
-<li>Enter the name of your common group (<em>e.g.</em> AllUsers)</li>
-<li>Enter "yes" or "y" to confirm</li>
-<li>Change the level if desired</li>
-<li>Run Scout2</li>
-</ol>
-
-<p><strong><em>Note</em></strong>: If you have already run Scout2 and do not wish to download the latest
-IAM configuration, use the following command to run an offline analysis:</p>
-<div class="highlight"><pre><code class="language-" data-lang="">./Scout2.py --ruleset_name isec --services iam --local
-</code></pre></div>
-<p>The following screenshot illustrates the IAM menu dropdown containing a
-security risk when IAM users do not belong to the configured common group.</p>
-
-<p><img src="/images/aws/awsscout2-iam-user-commongroup-1.png" alt="Screenshot: IAM menu dropdown when IAM users do not belong to the common group"></p>
-
-<p>When clicked-on, this link filters the list of IAM users to only display those
-who do not belong to the common IAM group. A colored warning sign appears,
-warning about this issue.</p>
-
-<p><img src="/images/aws/awsscout2-iam-user-commongroup-2.png" alt="Screenshot: Orange badge indicating that at least one user policy is attached to that IAM user"></p>
-
-<h3>Conclusion</h3>
-
-<p>Strict management of IAM users and tight control of their privileges is key in
-maintaining a secure AWS environment. When followed, the above recommendations
-should enable AWS administrators to manage IAM users with improved efficiency
-and lower the chances of overly privileged users to exist.</p>
-
- Tue, 24 Feb 2015 20:49:00 -0800
- http://l01cd3v.github.io/aws/2015/02/24/iam_user_management.html
- http://l01cd3v.github.io/aws/2015/02/24/iam_user_management.html
-
-
-
- Do not use your AWS root account
- <h3>What is the AWS root account?</h3>
-
-<p>The AWS root account is the account that was used -- or created -- when signing
-up with Amazon Web Services. This account has full access to all resources in
-the account and it is not possible to alter this configuration.</p>
-
-<h3>Risks of using the AWS root account</h3>
-
-<p>Using the AWS root account means that there is potential for its compromise.
-In particular, iSEC noticed that AWS customers who use the AWS root account
-tend to do the following:</p>
-
-<ol>
-<li>Share credentials between employees.</li>
-<li>Disable Multi-Factor Authentication (MFA) for convenience.</li>
-</ol>
-
-<p>Shared credentials, aside from increasing the risk of compromise during the
-sharing process, render credential rotation impractical due to the need for the
-newly-generated secret to be known by multiple parties. Sharing the AWS root
-account also undermines any effort towards using IAM and leveraging the
-fine-grained access controls it offers. Finally, shared credentials result in
-loss of the attribution ability, which makes auditing harder and may prevent
-successful investigation.</p>
-
-<h3>AWS Identity and Access Management (IAM)</h3>
-
-<p>AWS IAM allows account administrators to create users for every employee and
-grant them access to a limited set of services, actions, and resources. This
-allows AWS account administrators to apply the principle of least privilege,
-which dictates that a given user should only be able to access the information
-and resources that are necessary for them to perform tasks they are responsible
-for. Additionally, use of IAM allows AWS users to rotate credentials and revoke
-privileges without impacting other employees.</p>
-
-<p>AWS account administrators should create an <em>Administrator</em> IAM group, grant
-administrator privileges to this group, and create individual IAM users for
-each employee in charge of administrating the AWS account. When done, the AWS
-root password should be rotated and stored in a safe manner. Furthermore,
-additional credentials such as access keys and certificates should be deleted.</p>
-
-<h3>Important security consideration about the root account</h3>
-
-<p>AWS users should always enable MFA on their root account, even when the
-password is securely stored; it is important to realize that the password reset
-for the root account process only requires access to the email address
-associated with this account. <strong>This means that, without MFA, your production
-environment is only as secure as an email.</strong></p>
-
- Mon, 23 Feb 2015 08:42:00 -0800
- http://l01cd3v.github.io/aws/2015/02/23/do_not_use_your_root_account.html
- http://l01cd3v.github.io/aws/2015/02/23/do_not_use_your_root_account.html
-
-
-
- Announcing the AWS blog post series
- <p>Starting this month, iSEC Partners will start a series of blog posts related to
-AWS. The goal of these blog posts will be to:</p>
-
-<ul>
-<li>Discuss common security gaps in AWS environments</li>
-<li>Discuss common security gaps in the architecture of applications deployed in
-the cloud</li>
-<li>Describe methods and tools used to identify these security gaps</li>
-<li>Share tools and scripts that facilitate daily and secure work with AWS</li>
-<li>Share AWS policies that help improve the security posture of AWS environments</li>
-</ul>
-
-<p>To share material, iSEC created a new public
-<a target="_blank"
-href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a> repository
-on Github. The tools and policies shared in this repository will be discussed
-and explained in dedicated blog articles.</p>
-
-<p>Because iSEC has been assessing the security of AWS environment for several
-years, we have a number of ideas and articles in the pipe awaiting to be
-written and published. Our target goal is to publish at least on a bi-monthly
-basis at the beginning of the project, and adjust this publication rate after
-we catch up.</p>
-
-<p>Without further due, we will start this series with articles that discuss
-Identity and Access Management (IAM) common issues and best practices, and will
-present a strategy to improve one's security posture when using AWS.</p>
-
- Sun, 22 Feb 2015 22:24:00 -0800
- http://l01cd3v.github.io/aws/2015/02/22/announcing_the_aws_blog_post_series.html
- http://l01cd3v.github.io/aws/2015/02/22/announcing_the_aws_blog_post_series.html
-
-
-
-
diff --git a/_site/images/aws/awsscout2-ec2-cidr-friendlyname.png b/_site/images/aws/awsscout2-ec2-cidr-friendlyname.png
deleted file mode 100755
index 7543b71..0000000
Binary files a/_site/images/aws/awsscout2-ec2-cidr-friendlyname.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-iam-user-commongroup-1.png b/_site/images/aws/awsscout2-iam-user-commongroup-1.png
deleted file mode 100755
index 89d5130..0000000
Binary files a/_site/images/aws/awsscout2-iam-user-commongroup-1.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-iam-user-commongroup-2.png b/_site/images/aws/awsscout2-iam-user-commongroup-2.png
deleted file mode 100755
index b56ebca..0000000
Binary files a/_site/images/aws/awsscout2-iam-user-commongroup-2.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-iam-user-policy-1.png b/_site/images/aws/awsscout2-iam-user-policy-1.png
deleted file mode 100755
index 4580050..0000000
Binary files a/_site/images/aws/awsscout2-iam-user-policy-1.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-iam-user-policy-2.png b/_site/images/aws/awsscout2-iam-user-policy-2.png
deleted file mode 100755
index df519b1..0000000
Binary files a/_site/images/aws/awsscout2-iam-user-policy-2.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-user-nomfa-1.png b/_site/images/aws/awsscout2-user-nomfa-1.png
deleted file mode 100755
index 74c0ac8..0000000
Binary files a/_site/images/aws/awsscout2-user-nomfa-1.png and /dev/null differ
diff --git a/_site/images/aws/awsscout2-user-nomfa-2.png b/_site/images/aws/awsscout2-user-nomfa-2.png
deleted file mode 100755
index df37040..0000000
Binary files a/_site/images/aws/awsscout2-user-nomfa-2.png and /dev/null differ
diff --git a/_site/images/body-bg.png b/_site/images/body-bg.png
deleted file mode 100644
index 5e8c4c2..0000000
Binary files a/_site/images/body-bg.png and /dev/null differ
diff --git a/_site/images/highlight-bg.jpg b/_site/images/highlight-bg.jpg
deleted file mode 100644
index 355e089..0000000
Binary files a/_site/images/highlight-bg.jpg and /dev/null differ
diff --git a/_site/images/hr.png b/_site/images/hr.png
deleted file mode 100644
index d32f689..0000000
Binary files a/_site/images/hr.png and /dev/null differ
diff --git a/_site/index.html b/_site/index.html
deleted file mode 100644
index 56bdb54..0000000
--- a/_site/index.html
+++ /dev/null
@@ -1,845 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- l01cd3v.github.io
-
-
-
-
Last Tuesday (August 3rd), I presented "Access Keys Will Kill You Before You
-Kill The Password" at Black Hat US 2016. The summary is on the Black
-Hat website and the updated slide deck is available Here.
-This presentation aimed at highlighting risks associated with usage of AWS API
-access keys in environments that do not enforce MFA-protected API access, and
-documented strategies and IAM policies to help address these risks.
-
-
On Wednesday (August 4th), I presented Scout2 at Black Hat Arsenal. During two
-hours, I had the opportunity to demo Scout2 and meet users of the tool who
-shared valuable feedback with me. I look forward to implementing some of the
-features discussed during this event, including adding support for ECS and
-finishing the new rules generator.
-
-
As a reminder, Scout2 is available on Github, feedback is appreciated,
-and feature requests and pull requests are welcome. The Scout2 documentation is
-available at https://nccgroup.github.io/Scout2.
A significant challenge for companies using the cloud lies in ensuring that
-their firewall rules follow the principle of least privilege. It is
-extremely common nowadays to delegate management of security groups to developers, for
-both production and test environments. This means that security groups and
-their associated rules are managed by a much larger number of employees than
-what used to be the case in non-cloud environments, where a unique, smaller
-team was in charge of managing all firewall rules. Due to the more dynamic
-nature of cloud-based infrastructures, companies should review their cloud
-environment's firewall rules on a more frequent basis than for non cloud-based
-systems. Unfortunately, this is a difficult exercise due to the large number of
-CIDRs that may be whitelisted in a given AWS account. Keeping track of all
-known CIDRs and what hosts or networks they represent is not easy for
-employees, and is almost impossible for external auditors who must perform the
-review within a limited timeframe.
-
-
In this post, I will document how this issue can be addressed using the
-AWS-Recipes tools and
-Scout2.
-
-
Feed custom ip-ranges files to Scout2
-
-
Today, I am excited to announce that Scout2 accepts JSON files that
-contain known CIDRs along with arbitrary metadata such as the host or network
-they represent. When provided with such files, Scout2's report displays the
-"friendly name" of each known CIDR that is whitelisted in security group rules.
-This means that, instead of reviewing a list of obscure IP ranges, users of
-Scout2 may now rely on the name associated with each CIDR.
-
-
In order to use this new feature, Scout2 should be run with the following
-arguments:
-
./Scout2.py --profile nccgroup --ip-ranges ip-ranges-nccgroup.json ip-ranges-ncc-offices.json --ip-ranges-key-name name
-
-
In the above command line, Scout2 receives two ip-ranges JSON files via the
-"--ip-ranges" argument:
-
-
-
ip-ranges-nccgroup.json, which contains the public IP addresses in the AWS IP space in use
-
ip-ranges-ncc-offices.json, which contains the public IP addresses of several offices
-
-
-
Furthermore, the "--ip-ranges-key-name" argument indicates which JSON field to
-display as the "friendly name".
-
-
The following screenshot illustrates that, in the Scout2 report, the name of
-each known CIDR is displayed. When an IP which belongs to a known CIDR is
-whitelisted, the name of the corresponding CIDR is used. In this example,
-5.5.5.42/32 belongs to the 5.5.5.0/24 CIDR, which is associated with the "San
-Francisco" office. An "Unknown CIDR" value is displayed when an unknown value
-is whitelisted.
-
-
-
-
The next section of this blog post documents how users can create and manage
-these ip-ranges JSON files.
-
-
Manage known CIDRs with aws_recipes_create_ip_ranges.py
Automatically create ip-ranges files based on public IP addresses in AWS (Elastic IPs and EC2 instances)
-
Automatically create ip-ranges files based on IP addresses documented in a CSV file
-
Manually create and manage ip-ranges files
-
-
-
Each of these use cases is detailed in an example below, with detailed input,
-commands, and output contents.
-
-
Note: In the commands below, the "--debug" argument is used to
-output pretty-printed JSON, for documentation purposes.
-
-
Automatically create ip-ranges based on public IP addresses in an AWS account
-
-
First, this tool may be used to create an ip-ranges file that contains an AWS
-account's elastic IP addresses and EC2 instances' public IP addresses. By doing
-so, AWS users will be able to maintain a list of public IP addresses in the AWS
-IP space that are associated with their resources. Assuming that AWS
-credentials are configured under the "nccgroup" profile name, the command
-below may be used:
-
$ ./aws_recipes_create_ip_ranges.py --profile nccgroup --debug
-
-Fetching public IP information for the 'nccgroup' environment...
-...in us-east-1: EC2 instances
-...in us-east-1: Elastic IP addresses
-...in ap-northeast-1: EC2 instances
-...in ap-northeast-1: Elastic IP addresses
-...in eu-west-1: EC2 instances
-...in eu-west-1: Elastic IP addresses
-...in ap-southeast-1: EC2 instances
-...in ap-southeast-1: Elastic IP addresses
-...in ap-southeast-2: EC2 instances
-...in ap-southeast-2: Elastic IP addresses
-...in us-west-2: EC2 instances
-...in us-west-2: Elastic IP addresses
-...in us-west-1: EC2 instances
-...in us-west-1: Elastic IP addresses
-...in eu-central-1: EC2 instances
-...in eu-central-1: Elastic IP addresses
-...in sa-east-1: EC2 instances
-...in sa-east-1: Elastic IP addresses
-
-
My test environment has one elastic IP address that is not associated
-with an AWS resource, and one EC2 instance that has a non-elastic public IP.
-Executing the above command results in the creation of an
-"ip-ranges-nccgroup.json" file that has the following contents:
From experience, I know that many companies maintain a list of their
-public IP addresses, along with other network configuration information, in alternate formats, such as CSV. In
-order to help with the conversion, the tool supports reading CIDR information
-from CSV files. The tool was designed to be flexible and allow the creation of IP
-ranges from any CSV file. In this blog post, I provide two examples.
-
-
This first example demonstrates how to use the tool to build a JSON file based
-on the CSV column headers. Only attributes specified on the command line will
-be copied over.
-
-
Contents of test1.csv:
-
ip_prefix, discarded_value, name
-4.4.4.0/24, ncc group, NY office
-# This is a comment...
-5.5.5.0/24, ncc group, Seattle office
-
-
Command line to convert the contents of the CSV file into JSON:
-
./aws_recipes_create_ip_ranges.py --csv-ip-ranges test1.csv --attributes ip_prefix name --profile ncc-test1 --debug
-
The second example demonstrates how to use the tool to parse a CSV file with
-custom column names and separate columns for the base IP and subnet mask. The
-"--mappings" argument determines how columns will be mapped to the JSON
-file's attributes.
-
-
Contents of test2.csv
-
Base IP, Dotted Subnet Mask, Subnet Mask, Something, Name, Something else
-3.3.3.0, 255.255.255.0, /24, Value to discard, SF Office, Other value to discard
-
-
Command line to convert the contents of the CSV file into JSON:
In case CIDRs were not managed in a CSV file, the tools offers an interactive
-mode that may be leveraged to manually create a JSON ip-ranges file. The
-following snippet illustrates how to use the tool to interactively create new
-ip-ranges JSON files:
-
$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name
-
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-5.5.5.0/24
-You entered "5.5.5.0/24". Is that correct (y/n)?
-y
-Enter the 'name' value:
-San Francisco
-You entered "San Francisco". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-6.6.6.6/32
-You entered "6.6.6.6/32". Is that correct (y/n)?
-y
-Enter the 'name' value:
-San Francisco
-You entered "San Francisco". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-n
-
The tool can also automatically add new CIDRs to existing ip-ranges files:
-
$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name --debug
-
-Loading existing IP ranges from ip-ranges-ncc-offices.json
-Add a new IP prefix to the ip ranges (y/n)?
-y
-Enter the new IP prefix:
-7.7.7.7/32
-You entered "7.7.7.7/32". Is that correct (y/n)?
-y
-Enter the 'name' value:
-Seattle
-You entered "Seattle". Is that correct (y/n)?
-y
-Add a new IP prefix to the ip ranges (y/n)?
-n
-File 'ip-ranges-ncc-offices.json' already exists. Do you want to overwrite it (y/n)?
-y
-
-$ cat ip-ranges-ncc-offices.json
-{
- "createDate": "2015-11-16-22-44-38",
- "prefixes": [
- {
- "ip_prefix": "5.5.5.0/24",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "6.6.6.6/32",
- "name": "San Francisco"
- },
- {
- "ip_prefix": "7.7.7.7/32",
- "name": "Seattle"
- }
- ]
-}
-
-
Conclusion
-
-
This addition to Scout2 provides AWS account administrators and auditors with
-an improved insight into their environment. Usage of this feature should result
-in further hardened security groups because detection of unknown whitelisted
-CIDRs and understanding of existing rules is significantly easier.
-
-
I am currently working on a major rework of Scout2's reporting engine,
-which will further improve reporting and allow creation of new alerts when an
-unknown CIDR is whitelisted.
Today, I am excited to announce that support for Redshift was added in
-Scout2. By default, Scout2 will fetch information about your Redshift clusters,
-cluster parameter groups, and cluster security groups if you still use
-EC2-Classic. At this stage, Scout2 comes with six Redshift security rules that
-are enabled by default:
-
-
-
Clusters
-
-
-
Check whether version upgrade is enabled
-
Check whether the cluster is publicly accessible
-
Check whether database encryption is enabled
-
-
Cluster parameter groups
-
-
-
Check whether SSL/TLS is required to access the database
-
Check whether user activity logging is enabled
-
-
Cluster security groups (EC2-classic)
-
-
-
Check whether the security group allows access to all IP addresses (0.0.0.0/0)
-
-
-
-
Scout2 was first released over a year and a half ago, and proved to be extremely
-helpful when performing AWS configuration reviews. While
-Scout2's initial release only supported three services (IAM, EC2, and S3) and
-included thirteen security checks, the tool rapidly grew to add support for RDS
-and CloudTrail. Furthermore, the tool now offers over fifty tests throughout
-these five supported services. I hope that support for Redshift will bring
-value to users of Scout2, and welcome feature requests, bug reports, and
-recommendations on Github at
-https://github.com/iSECPartners/Scout2/issues.
With boto3 being stable and generally available1, I took the opportunity
-to migrate Scout2 and AWS-recipes to boto3. As part of that migration
-effort, I decided to publish the formerly-known-as AWSUtils repository -- used
-by Scout2 and AWS-recipes -- as a python package required by these tools,
-rather than requiring users to work with Git submodules. I've also added more
-flexibility when working with MFA-protected API calls and improved versioning
-across the project.
-
-
opinel
-
-
To avoid name conflicts, I decided to rename the shared AWSUtils code to a
-less misleading name: opinel. The opinel package is published on PyPI, and thus can
-be installed using pip and easy_install. The corresponding source code is still
-open-sourced on Github at https://github.com/iSECPartners/opinel.
-As a result, Scout2 and AWS-recipes have been modified to list opinel as a
-requirement, which significantly simplifies installation and management of this
-shared code.
-
-
Support for Python 2.7 and 3.x
-
-
Because boto3 supports both Python2 and Python3, I decided to make sure that
-the code built on top of that package has similar properties. As a result,
-the latest versions of Scout2 and AWS-recipes support Python 2.7 and 3.x.
-Note that opinel will NOT work with Python 2.6.
-
-
Modification of the MFA workflow
-
-
As requested by a user of AWS-recipes2, I modified the workflow when
-using MFA-protected API access to no longer store the long-lived credentials
-in a separate file. As a result, the .aws/credentials.no-mfa file is no
-longer supported and all credentials are stored in the standard AWS credentials
-file under .aws/credentials. Usage of the existing tools remains unchanged,
-but the long-lived credentials are now accessible via a new profile name:
-profile_name-nomfa. This allows users to work with both STS and long-lived
-credentials if need be.
-
-
If you already had configured your environment to work with MFA-protected API
-access, you will need to copy your long-lived credentials back to the
-.aws/credentials file. This can be done with a simple command such as the
-following:
-
cat ~/.aws/credentials.no-mfa | sed -e 's/]$/-nomfa]/g' >> ~/.aws/credentials
-
-
Support to use assumed-role credentials
-
-
With this new workflow implemented, I created a new recipe that allows
-configuration of role-credentials in the .aws/credentials file. When the following
-command is run, it uses the credentials associated with the isecpartners
-profile to request role credentials for the IAM-Scout2 role. The role
-credentials are then written in the .aws/credentials file in a new profile
-named isecpartners-Scout2, which is the profile name appended by the role
-session name.
Users can then use their favorite tools that support profiles. For example,
-Scout2 could be run with the following command line:
-
$ ./Scout2.py --profile isecpartners-Scout2
-
-
Note that this recipe supports MFA if the assumed role requires it:
-
-
-
If you never configured your environment to work with MFA, you can provide your MFA serial number (ARN) and current token code as arguments.
-
If you already configured your environment to work with MFA and stored your MFA serial in the .aws/credentials file, you just need to pass your token code as an additional argument.
-
Finally, if you already initiated an STS session, you do not need to provide a new token code and can run the command as above.
-
-
-
Conclusion
-
-
With the release of opinel, I hope to simplify distribution and management of
-the code shared between Scout2 and AWS-recipes. Additionally, I
-significantly modified the workflow and credentials storage when working with
-MFA-protected API calls, which allows users to use both their long-lived and STS
-credentials.
The previous IAM user management strategy post discussed how
-usage of IAM groups enables AWS administrators to consistently grant privileges
-and enforce a number of security rules (such as MFA-protected API access). This
-blog post will build on this idea by introducing category groups and
-documenting new tools to improve IAM user management.
-
-
Categorize your IAM users
-
-
For a variety of reasons, applying a single set of security rules to all IAM
-users is not always practical. For example, because many applications running
-in AWS predate IAM roles, numerous environments still rely on the existence of
-headless IAM users. Additionally, third parties may be granted access to an AWS
-account for a number of reasons but may not be able to comply with the same set
-of security rules that employees follow. For this reason, NCC recommends using
-category groups to sort IAM users and reliably enforce appropriate security
-measures. For example, one group for all human users and a second for all headless users may be
-created: MFA-protected API access and password management are not relevant for
-headless users. Furthermore, human users may be categorized into several groups
-such as employees and contractors: API access can be restricted to the
-corporate IP range for employees but might not be achievable for contractors.
-
-
Note 1: The set of category groups should define all types of IAM users that
-may exist in your AWS account and each IAM user should belong to one -- and
-only one -- category group (they may belong to other groups though).
-
-
Note 2: The common group and category groups should be used to enable enforcing
-security in one's AWS environment. Policies attached to these groups should be
-carefully reviewed and grant the minimum set of privileges necessary for this
-type of IAM user (e.g. credential management for humans).
-
-
Example of category groups
-
-
The rest of this article describes a number of tools developed and used by
-NCC to help implement this IAM user management strategy. These tools can be found
-in the AWS-Recipes repository. We will
-use our test AWS environment as an example, in which we use three category groups in
-addition to the AllUsers common group:
-
-
-
AllHumans, the group all employees must belong to.
-
AllHeadlessUsers, the group all headless IAM users must belong to.
-
AllMisconfiguredUsers, a placeholder for sample misconfigured users.
-
-
-
We also have an IAM user naming convention that requires usernames to match the
-following schema:
-
-
-
Employees: firstname initial appended with lastname
-
Headless user: name of the service prefixed with HeadlessUser-
-
Misconfigured: description of the misconfiguration prefixed with MisconfiguredUser-
-
-
-
Based on these rules, we created a configuration file stored under
-.aws/recipes/isecpartners.json, with isecpartners matching the profile's
-name. If you do not use profiles, the configuration will be under
-.aws/recipes/default.json.
This configuration file declares the name of the common IAM group and two lists
-related to the categorization of IAM users:
-
-
-
A list of category groups.
-
A list of regular expressions matching our naming convention.
-
-
-
Note 1: If you do not have a naming convention in place to distinguish the
-type of user, remove the category_regex attribute from your configuration
-file.
-
-
Note 2: If a regular expression is only applicable to a subset of category
-groups, you must ensure that both lists have the same length and use an empty
-string for groups that cannot be automatically associated (see the
-AllHumanUsers group in our example).
-
-
Note 3: Use of a configuration file is not necessary as all values may be
-passed as command line arguments. If a configuration file exists and a value is
-passed as an argument, the value passed via the command line will be used.
The purpose of this tool is to create IAM groups whose name matches the common
-and category groups specified in the above configuration file. Running the
-following command results in four new groups being created if they did not
-already exist.
This tool iterates through all IAM users and attempts to automatically detect
-the IAM groups each user should belong to. For convenience, we recommend adding
-the following to your AWS recipes configuration files:
This specifies default values for additional arguments to be set when running
-aws_iam_sort_users.py. Specifically, with these values, running this tool
-will automatically add all IAM users to the common group AllUsers and will
-not attempt to create the default groups (not necessary as we already did
-this). Additionally, this tool checks that each IAM user belongs to one of the
-category groups. If this is not the case and the username matches a regular
-expression, the user is automatically added to the matching category group. Otherwise, a
-multi-choice prompt appears to allow manual selection of the appropriate
-category group.
-
-
Additional advantages of configuration files
-
-
Besides helping with simplification of these tools' usage, this new AWS-recipe
-configuration file can be used across tools, allowing for more consistent
-rule enforcement. For example, the
-aws_iam_create_user.py.
-tool uses this configuration file and applies the same business logic to add
-users to the common group and appropriate category group at user creation time. In
-our test environment, for example, running the following command automatically
-added the new user to the MisconfiguredUser group:
-
$ ./aws_iam_create_user.py --profile isecpartners --users MisconfiguredUser-BlogPostExample
-Creating user MisconfiguredUser-BlogPostExample...
-Save unencrypted value (y/n)? y
-User 'MisconfiguredUser-BlogPostExample' does not belong to the mandatory common group 'AllUsers'. Do you want to remediate this now (y/n)? y
-User 'MisconfiguredUser-BlogPostExample' does not belong to any of the category group (AllHumanUsers, AllHeadlessUsers, AllMisconfiguredUsers). Automatically adding...
-Enabling MFA for user MisconfiguredUser-BlogPostExample...
-
-
Conclusion
-
-
While efficient and reliable management of IAM users can be challenging, using
-the right strategy and tools significantly simplifies this process. Creation
-and use of a naming convention for IAM users enables
-automated user management and enforcement of security rules.
diff --git a/_site/aws/2015/02/22/announcing_the_aws_blog_post_series.html b/aws/2015/02/22/announcing_the_aws_blog_post_series.html
similarity index 100%
rename from _site/aws/2015/02/22/announcing_the_aws_blog_post_series.html
rename to aws/2015/02/22/announcing_the_aws_blog_post_series.html
diff --git a/_site/aws/2015/02/23/do_not_use_your_root_account.html b/aws/2015/02/23/do_not_use_your_root_account.html
similarity index 100%
rename from _site/aws/2015/02/23/do_not_use_your_root_account.html
rename to aws/2015/02/23/do_not_use_your_root_account.html
diff --git a/_site/aws/2015/02/24/iam_user_management.html b/aws/2015/02/24/iam_user_management.html
similarity index 100%
rename from _site/aws/2015/02/24/iam_user_management.html
rename to aws/2015/02/24/iam_user_management.html
diff --git a/_site/aws/2015/04/02/use_and_enforce_mfa.html b/aws/2015/04/02/use_and_enforce_mfa.html
similarity index 100%
rename from _site/aws/2015/04/02/use_and_enforce_mfa.html
rename to aws/2015/04/02/use_and_enforce_mfa.html
diff --git a/_site/aws/2015/04/03/session_management_tools.html b/aws/2015/04/03/session_management_tools.html
similarity index 100%
rename from _site/aws/2015/04/03/session_management_tools.html
rename to aws/2015/04/03/session_management_tools.html
diff --git a/_site/aws/2015/06/09/iam_user_management_2.html b/aws/2015/06/09/iam_user_management_2.html
similarity index 100%
rename from _site/aws/2015/06/09/iam_user_management_2.html
rename to aws/2015/06/09/iam_user_management_2.html
diff --git a/_site/aws/2015/08/03/boto3_opinel_scout_recipes.html b/aws/2015/08/03/boto3_opinel_scout_recipes.html
similarity index 100%
rename from _site/aws/2015/08/03/boto3_opinel_scout_recipes.html
rename to aws/2015/08/03/boto3_opinel_scout_recipes.html
diff --git a/_site/aws/2015/08/06/scout2_supports_redshift.html b/aws/2015/08/06/scout2_supports_redshift.html
similarity index 100%
rename from _site/aws/2015/08/06/scout2_supports_redshift.html
rename to aws/2015/08/06/scout2_supports_redshift.html
diff --git a/_site/aws/2015/11/17/ip_ranges_management.html b/aws/2015/11/17/ip_ranges_management.html
similarity index 100%
rename from _site/aws/2015/11/17/ip_ranges_management.html
rename to aws/2015/11/17/ip_ranges_management.html
diff --git a/_site/aws/2016/08/08/blackhat_slides.html b/aws/2016/08/08/blackhat_slides.html
similarity index 100%
rename from _site/aws/2016/08/08/blackhat_slides.html
rename to aws/2016/08/08/blackhat_slides.html
diff --git a/_site/categories/aws/index.html b/categories/aws/index.html
similarity index 100%
rename from _site/categories/aws/index.html
rename to categories/aws/index.html
diff --git a/_site/categories/index.html b/categories/index.html
similarity index 100%
rename from _site/categories/index.html
rename to categories/index.html
diff --git a/categories/index.md b/categories/index.md
deleted file mode 100644
index fe93bc6..0000000
--- a/categories/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-layout: archives
-title: Blog Posts
----
-
-{% for category in site.categories %}
-
-{% endfor %}
diff --git a/feed.xml b/feed.xml
index 055c4dd..627e769 100644
--- a/feed.xml
+++ b/feed.xml
@@ -1,21 +1,1084 @@
----
-layout: null
----
- {{ site.name | xml_escape }}
- {{ site.description | xml_escape }}
- {{ site.url }}
-
- {% for post in site.posts limit:10 %}
-
- {{ post.title | xml_escape }}
- {{ post.content | xml_escape }}
- {{ post.date | date: "%a, %d %b %Y %H:%M:%S %z" }}
- {{ site.url }}{{ post.url }}
- {{ site.url }}{{ post.url }}
-
- {% endfor %}
+ l01cd3v.github.io
+
+ http://l01cd3v.github.io
+
+
+
+ Post Black Hat US 2016 blog post
+ <p>Last Tuesday (August 3rd), I presented "Access Keys Will Kill You Before You
+Kill The Password" at Black Hat US 2016. The summary is on the <a
+target="_blank"
+href="https://www.blackhat.com/us-16/briefings.html#access-keys-will-kill-you-before-you-kill-the-password">Black
+Hat website</a> and the updated slide deck is available <a
+href="slides/us-16-Simon-Access-Keys-Will-Kill-You-Before-You-Kill-The-Password.pdf">Here</a>.
+This presentation aimed at highlighting risks associated with usage of AWS API
+access keys in environments that do not enforce MFA-protected API access, and
+documented strategies and IAM policies to help address these risks.</p>
+
+<p>On Wednesday (August 4th), I presented Scout2 at Black Hat Arsenal. During two
+hours, I had the opportunity to demo Scout2 and meet users of the tool who
+shared valuable feedback with me. I look forward to implementing some of the
+features discussed during this event, including adding support for ECS and
+finishing the new rules generator.</p>
+
+<p>As a reminder, Scout2 is available on <a target="_blank"
+href="https://github.com/nccgroup/Scout2">Github</a>, feedback is appreciated,
+and feature requests and pull requests are welcome. The Scout2 documentation is
+available at <a target="_blank"
+href="https://nccgroup.github.io/Scout2">https://nccgroup.github.io/Scout2</a>.</p>
+
+ Mon, 08 Aug 2016 23:28:00 -0700
+ http://l01cd3v.github.io/aws/2016/08/08/blackhat_slides.html
+ http://l01cd3v.github.io/aws/2016/08/08/blackhat_slides.html
+
+
+
+ Efficient review of AWS security groups' CIDR grants
+ <p>A significant challenge for companies using the cloud lies in ensuring that
+their firewall rules follow the principle of least privilege. It is
+extremely common nowadays to delegate management of security groups to developers, for
+both production and test environments. This means that security groups and
+their associated rules are managed by a much larger number of employees than
+what used to be the case in non-cloud environments, where a unique, smaller
+team was in charge of managing all firewall rules. Due to the more dynamic
+nature of cloud-based infrastructures, companies should review their cloud
+environment's firewall rules on a more frequent basis than for non cloud-based
+systems. Unfortunately, this is a difficult exercise due to the large number of
+<a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing">CIDRs</a> that may be whitelisted in a given AWS account. Keeping track of all
+known CIDRs and what hosts or networks they represent is not easy for
+employees, and is almost impossible for external auditors who must perform the
+review within a limited timeframe.</p>
+
+<p>In this post, I will document how this issue can be addressed using the
+<a href="https://github.com/iSECPartners/AWS-recipes">AWS-Recipes</a> tools and
+<a href="https://github.com/iSECPartners/Scout2">Scout2</a>.</p>
+
+<h3>Feed custom ip-ranges files to Scout2</h3>
+
+<p>Today, I am excited to announce that Scout2 accepts JSON files that
+contain known CIDRs along with arbitrary metadata such as the host or network
+they represent. When provided with such files, Scout2's report displays the
+"friendly name" of each known CIDR that is whitelisted in security group rules.
+This means that, instead of reviewing a list of obscure IP ranges, users of
+Scout2 may now rely on the name associated with each CIDR.</p>
+
+<p>In order to use this new feature, Scout2 should be run with the following
+arguments:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">./Scout2.py --profile nccgroup --ip-ranges ip-ranges-nccgroup.json ip-ranges-ncc-offices.json --ip-ranges-key-name name
+</code></pre></div>
+<p>In the above command line, Scout2 receives two ip-ranges JSON files via the
+"--ip-ranges" argument:</p>
+
+<ul>
+<li>ip-ranges-nccgroup.json, which contains the public IP addresses in the AWS IP space in use</li>
+<li>ip-ranges-ncc-offices.json, which contains the public IP addresses of several offices</li>
+</ul>
+
+<p>Furthermore, the "--ip-ranges-key-name" argument indicates which JSON field to
+display as the "friendly name".</p>
+
+<p>The following screenshot illustrates that, in the Scout2 report, the name of
+each known CIDR is displayed. When an IP which belongs to a known CIDR is
+whitelisted, the name of the corresponding CIDR is used. In this example,
+5.5.5.42/32 belongs to the 5.5.5.0/24 CIDR, which is associated with the "San
+Francisco" office. An "Unknown CIDR" value is displayed when an unknown value
+is whitelisted.</p>
+
+<p><img src="/images/aws/awsscout2-ec2-cidr-friendlyname.png" alt="Screenshot: Security group rules display the name of each known CIDRs"></p>
+
+<p>The next section of this blog post documents how users can create and manage
+these ip-ranges JSON files.</p>
+
+<h3>Manage known CIDRs with aws_recipes_create_ip_ranges.py</h3>
+
+<p>With AWS releasing their public IP address ranges, I decided to create a tool
+that allows creation and management of arbitrary IP address ranges using the
+same JSON format. The tool is released on GitHub at
+<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_create_ip_ranges.py">https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_create_ip_ranges.py</a>
+and may be used in several scenarios:</p>
+
+<ul>
+<li>Automatically create ip-ranges files based on public IP addresses in AWS (Elastic IPs and EC2 instances)</li>
+<li>Automatically create ip-ranges files based on IP addresses documented in a CSV file</li>
+<li>Manually create and manage ip-ranges files</li>
+</ul>
+
+<p>Each of these use cases is detailed in an example below, with detailed input,
+commands, and output contents.</p>
+
+<p><strong><em>Note:</em></strong> In the commands below, the "--debug" argument is used to
+output pretty-printed JSON, for documentation purposes.</p>
+
+<h4>Automatically create ip-ranges based on public IP addresses in an AWS account</h4>
+
+<p>First, this tool may be used to create an ip-ranges file that contains an AWS
+account's elastic IP addresses and EC2 instances' public IP addresses. By doing
+so, AWS users will be able to maintain a list of public IP addresses in the AWS
+IP space that are associated with their resources. Assuming that AWS
+credentials are configured under the "nccgroup" profile name, the command
+below may be used:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --profile nccgroup --debug
+
+Fetching public IP information for the 'nccgroup' environment...
+...in us-east-1: EC2 instances
+...in us-east-1: Elastic IP addresses
+...in ap-northeast-1: EC2 instances
+...in ap-northeast-1: Elastic IP addresses
+...in eu-west-1: EC2 instances
+...in eu-west-1: Elastic IP addresses
+...in ap-southeast-1: EC2 instances
+...in ap-southeast-1: Elastic IP addresses
+...in ap-southeast-2: EC2 instances
+...in ap-southeast-2: Elastic IP addresses
+...in us-west-2: EC2 instances
+...in us-west-2: Elastic IP addresses
+...in us-west-1: EC2 instances
+...in us-west-1: Elastic IP addresses
+...in eu-central-1: EC2 instances
+...in eu-central-1: Elastic IP addresses
+...in sa-east-1: EC2 instances
+...in sa-east-1: Elastic IP addresses
+</code></pre></div>
+<p>My test environment has one elastic IP address that is not associated
+with an AWS resource, and one EC2 instance that has a non-elastic public IP.
+Executing the above command results in the creation of an
+"ip-ranges-nccgroup.json" file that has the following contents:</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-16-22-49-27"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"instance_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"i-11223344"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.1.1.1"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"is_elastic"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Test EC2 instance"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"region"</span><span class="p">:</span><span class="w"> </span><span class="s2">"us-west-2"</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"instance_id"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.2.2.2"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"is_elastic"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"region"</span><span class="p">:</span><span class="w"> </span><span class="s2">"us-west-2"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<h4>Automatically create ip-ranges from CSV files</h4>
+
+<p>From experience, I know that many companies maintain a list of their
+public IP addresses, along with other network configuration information, in alternate formats, such as CSV. In
+order to help with the conversion, the tool supports reading CIDR information
+from CSV files. The tool was designed to be flexible and allow the creation of IP
+ranges from any CSV file. In this blog post, I provide two examples.</p>
+
+<p>This first example demonstrates how to use the tool to build a JSON file based
+on the CSV column headers. Only attributes specified on the command line will
+be copied over.</p>
+
+<p>Contents of test1.csv:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">ip_prefix, discarded_value, name
+4.4.4.0/24, ncc group, NY office
+# This is a comment...
+5.5.5.0/24, ncc group, Seattle office
+</code></pre></div>
+<p>Command line to convert the contents of the CSV file into JSON:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">./aws_recipes_create_ip_ranges.py --csv-ip-ranges test1.csv --attributes ip_prefix name --profile ncc-test1 --debug
+</code></pre></div>
+<p>Contents of ip-ranges-ncc-test1.json:</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-17-10-22-42"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4.4.4.0/24"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" NY office"</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5.5.5.0/24"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" Seattle office"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<p>The second example demonstrates how to use the tool to parse a CSV file with
+custom column names and separate columns for the base IP and subnet mask. The
+"--mappings" argument determines how columns will be mapped to the JSON
+file's attributes.</p>
+
+<p>Contents of test2.csv</p>
+<div class="highlight"><pre><code class="language-" data-lang="">Base IP, Dotted Subnet Mask, Subnet Mask, Something, Name, Something else
+3.3.3.0, 255.255.255.0, /24, Value to discard, SF Office, Other value to discard
+</code></pre></div>
+<p>Command line to convert the contents of the CSV file into JSON:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">./aws_recipes_create_ip_ranges.py --csv-ip-ranges test2.csv --attributes ip_prefix mask name --mappings 0 2 4 --profile ncc-test2 --skip-first-line --debug
+</code></pre></div>
+<p>Contents of ip-ranges-ncc-test2.json</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-17-10-07-22"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"3.3.3.0/24"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">" SF Office"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<h4>Manually create and update ip-ranges</h4>
+
+<p>In case CIDRs were not managed in a CSV file, the tools offers an interactive
+mode that may be leveraged to manually create a JSON ip-ranges file. The
+following snippet illustrates how to use the tool to interactively create new
+ip-ranges JSON files:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name
+
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+5.5.5.0/24
+You entered "5.5.5.0/24". Is that correct (y/n)?
+y
+Enter the 'name' value:
+San Francisco
+You entered "San Francisco". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+6.6.6.6/32
+You entered "6.6.6.6/32". Is that correct (y/n)?
+y
+Enter the 'name' value:
+San Francisco
+You entered "San Francisco". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+n
+</code></pre></div>
+<p>Contents of ip-ranges-ncc-offices.json:</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"createDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2015-11-16-22-44-38"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"prefixes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5.5.5.0/24"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"San Francisco"</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"ip_prefix"</span><span class="p">:</span><span class="w"> </span><span class="s2">"6.6.6.6/32"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"San Francisco"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<p>The tool can also automatically add new CIDRs to existing ip-ranges files:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name --debug
+
+Loading existing IP ranges from ip-ranges-ncc-offices.json
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+7.7.7.7/32
+You entered "7.7.7.7/32". Is that correct (y/n)?
+y
+Enter the 'name' value:
+Seattle
+You entered "Seattle". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+n
+File 'ip-ranges-ncc-offices.json' already exists. Do you want to overwrite it (y/n)?
+y
+
+$ cat ip-ranges-ncc-offices.json
+{
+ "createDate": "2015-11-16-22-44-38",
+ "prefixes": [
+ {
+ "ip_prefix": "5.5.5.0/24",
+ "name": "San Francisco"
+ },
+ {
+ "ip_prefix": "6.6.6.6/32",
+ "name": "San Francisco"
+ },
+ {
+ "ip_prefix": "7.7.7.7/32",
+ "name": "Seattle"
+ }
+ ]
+}
+</code></pre></div>
+<h3>Conclusion</h3>
+
+<p>This addition to Scout2 provides AWS account administrators and auditors with
+an improved insight into their environment. Usage of this feature should result
+in further hardened security groups because detection of unknown whitelisted
+CIDRs and understanding of existing rules is significantly easier.</p>
+
+<p>I am currently working on a major rework of Scout2's reporting engine,
+which will further improve reporting and allow creation of new alerts when an
+unknown CIDR is whitelisted.</p>
+
+ Tue, 17 Nov 2015 08:00:00 -0800
+ http://l01cd3v.github.io/aws/2015/11/17/ip_ranges_management.html
+ http://l01cd3v.github.io/aws/2015/11/17/ip_ranges_management.html
+
+
+
+ Redshift support added in Scout2
+ <p>Today, I am excited to announce that support for Redshift was added in
+Scout2. By default, Scout2 will fetch information about your Redshift clusters,
+cluster parameter groups, and cluster security groups if you still use
+EC2-Classic. At this stage, Scout2 comes with six Redshift security rules that
+are enabled by default:</p>
+
+<ul>
+<li>Clusters
+
+<ul>
+<li>Check whether version upgrade is enabled</li>
+<li>Check whether the cluster is publicly accessible</li>
+<li>Check whether database encryption is enabled</li>
+</ul></li>
+<li>Cluster parameter groups
+
+<ul>
+<li>Check whether SSL/TLS is required to access the database</li>
+<li>Check whether user activity logging is enabled</li>
+</ul></li>
+<li>Cluster security groups (EC2-classic)
+
+<ul>
+<li>Check whether the security group allows access to all IP addresses (0.0.0.0/0)</li>
+</ul></li>
+</ul>
+
+<p>Scout2 was first released over a year and a half ago, and proved to be extremely
+helpful when performing AWS configuration reviews. While
+Scout2's initial release only supported three services (IAM, EC2, and S3) and
+included thirteen security checks, the tool rapidly grew to add support for RDS
+and CloudTrail. Furthermore, the tool now offers over fifty tests throughout
+these five supported services. I hope that support for Redshift will bring
+value to users of Scout2, and welcome feature requests, bug reports, and
+recommendations on Github at
+<a href="https://github.com/iSECPartners/Scout2/issues">https://github.com/iSECPartners/Scout2/issues</a>.</p>
+
+ Thu, 06 Aug 2015 08:39:00 -0700
+ http://l01cd3v.github.io/aws/2015/08/06/scout2_supports_redshift.html
+ http://l01cd3v.github.io/aws/2015/08/06/scout2_supports_redshift.html
+
+
+
+ Introducing opinel: Scout2's favorite tool
+ <p>With boto3 being stable and generally available<sup><a href="https://aws.amazon.com/about-aws/whats-new/2015/06/boto3-aws-sdk-for-python-version-3-is-now-generally-available">1</a></sup>, I took the opportunity
+to migrate Scout2 and AWS-recipes to boto3. As part of that migration
+effort, I decided to publish the formerly-known-as AWSUtils repository -- used
+by Scout2 and AWS-recipes -- as a python package required by these tools,
+rather than requiring users to work with Git submodules. I've also added more
+flexibility when working with MFA-protected API calls and improved versioning
+across the project.</p>
+
+<h3>opinel</h3>
+
+<p>To avoid name conflicts, I decided to rename the shared AWSUtils code to a
+less misleading name: opinel. The opinel package is published on <a href="https://pypi.python.org/pypi/opinel">PyPI</a>, and thus can
+be installed using pip and easy_install. The corresponding source code is still
+open-sourced on Github at <a href="https://github.com/iSECPartners/opinel">https://github.com/iSECPartners/opinel</a>.
+As a result, Scout2 and AWS-recipes have been modified to list opinel as a
+requirement, which significantly simplifies installation and management of this
+shared code.</p>
+
+<h3>Support for Python 2.7 and 3.x</h3>
+
+<p>Because boto3 supports both Python2 and Python3, I decided to make sure that
+the code built on top of that package has similar properties. As a result,
+the latest versions of Scout2 and AWS-recipes support Python 2.7 and 3.x.
+Note that opinel will <strong>NOT</strong> work with Python 2.6.</p>
+
+<h3>Modification of the MFA workflow</h3>
+
+<p>As requested by a user of AWS-recipes<sup><a href="https://github.com/iSECPartners/opinel/issues/4">2</a></sup>, I modified the workflow when
+using MFA-protected API access to no longer store the long-lived credentials
+in a separate file. As a result, the <em>.aws/credentials.no-mfa</em> file is no
+longer supported and all credentials are stored in the standard AWS credentials
+file under <em>.aws/credentials</em>. Usage of the existing tools remains unchanged,
+but the long-lived credentials are now accessible via a new profile name:
+<em>profile_name-nomfa</em>. This allows users to work with both STS and long-lived
+credentials if need be.</p>
+
+<p>If you already had configured your environment to work with MFA-protected API
+access, you will need to copy your long-lived credentials back to the
+<em>.aws/credentials</em> file. This can be done with a simple command such as the
+following:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">cat ~/.aws/credentials.no-mfa | sed -e 's/]$/-nomfa]/g' >> ~/.aws/credentials
+</code></pre></div>
+<h3>Support to use assumed-role credentials</h3>
+
+<p>With this new workflow implemented, I created a new recipe that allows
+configuration of role-credentials in the <em>.aws/credentials</em> file. When the following
+command is run, it uses the credentials associated with the <em>isecpartners</em>
+profile to request role credentials for the IAM-Scout2 role. The role
+credentials are then written in the <em>.aws/credentials</em> file in a new profile
+named <em>isecpartners-Scout2</em>, which is the profile name appended by the role
+session name.</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_assume_role.py --profile isecpartners --role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/IAM-Scout2 --role-session-name Scout2
+</code></pre></div>
+<p>Users can then use their favorite tools that support profiles. For example,
+Scout2 could be run with the following command line:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./Scout2.py --profile isecpartners-Scout2
+</code></pre></div>
+<p>Note that this recipe supports MFA if the assumed role requires it:</p>
+
+<ul>
+<li>If you never configured your environment to work with MFA, you can provide your MFA serial number (ARN) and current token code as arguments.</li>
+<li>If you already configured your environment to work with MFA and stored your MFA serial in the <em>.aws/credentials</em> file, you just need to pass your token code as an additional argument.</li>
+<li>Finally, if you already initiated an STS session, you do not need to provide a new token code and can run the command as above.</li>
+</ul>
+
+<h3>Conclusion</h3>
+
+<p>With the release of opinel, I hope to simplify distribution and management of
+the code shared between Scout2 and AWS-recipes. Additionally, I
+significantly modified the workflow and credentials storage when working with
+MFA-protected API calls, which allows users to use both their long-lived and STS
+credentials.</p>
+
+ Mon, 03 Aug 2015 11:08:00 -0700
+ http://l01cd3v.github.io/aws/2015/08/03/boto3_opinel_scout_recipes.html
+ http://l01cd3v.github.io/aws/2015/08/03/boto3_opinel_scout_recipes.html
+
+
+
+ IAM user management strategy (part 2)
+ <p>The previous <a href="/aws/2015/02/24/iam_user_management.html">IAM user management strategy</a> post discussed how
+usage of IAM groups enables AWS administrators to consistently grant privileges
+and enforce a number of security rules (such as MFA-protected API access). This
+blog post will build on this idea by introducing category groups and
+documenting new tools to improve IAM user management.</p>
+
+<h3>Categorize your IAM users</h3>
+
+<p>For a variety of reasons, applying a single set of security rules to all IAM
+users is not always practical. For example, because many applications running
+in AWS predate IAM roles, numerous environments still rely on the existence of
+headless IAM users. Additionally, third parties may be granted access to an AWS
+account for a number of reasons but may not be able to comply with the same set
+of security rules that employees follow. For this reason, NCC recommends using
+category groups to sort IAM users and reliably enforce appropriate security
+measures. For example, one group for all human users and a second for all headless users may be
+created: MFA-protected API access and password management are not relevant for
+headless users. Furthermore, human users may be categorized into several groups
+such as employees and contractors: API access can be restricted to the
+corporate IP range for employees but might not be achievable for contractors.</p>
+
+<p><em>Note 1:</em> The set of category groups should define all types of IAM users that
+may exist in your AWS account and each IAM user should belong to one -- and
+only one -- category group (they may belong to other groups though).</p>
+
+<p><em>Note 2:</em> The common group and category groups should be used to enable enforcing
+security in one's AWS environment. Policies attached to these groups should be
+carefully reviewed and grant the minimum set of privileges necessary for this
+type of IAM user (<em>e.g.</em> credential management for humans).</p>
+
+<h3>Example of category groups</h3>
+
+<p>The rest of this article describes a number of tools developed and used by
+NCC to help implement this IAM user management strategy. These tools can be found
+in the <a href="https://github.com/iSECPartners/AWS-recipes">AWS-Recipes</a> repository. We will
+use our test AWS environment as an example, in which we use three category groups in
+addition to the <em>AllUsers</em> common group:</p>
+
+<ol>
+<li><em>AllHumans</em>, the group all employees must belong to.</li>
+<li><em>AllHeadlessUsers</em>, the group all headless IAM users must belong to.</li>
+<li><em>AllMisconfiguredUsers</em>, a placeholder for sample misconfigured users.</li>
+</ol>
+
+<p>We also have an IAM user naming convention that requires usernames to match the
+following schema:</p>
+
+<ol>
+<li>Employees: firstname initial appended with lastname</li>
+<li>Headless user: name of the service prefixed with <em>HeadlessUser-</em></li>
+<li>Misconfigured: description of the misconfiguration prefixed with <em>MisconfiguredUser-</em></li>
+</ol>
+
+<p>Based on these rules, we created a configuration file stored under
+<em>.aws/recipes/isecpartners.json</em>, with <em>isecpartners</em> matching the profile's
+name. If you do not use profiles, the configuration will be under
+<em>.aws/recipes/default.json</em>.</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"common_groups"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"AllUsers"</span><span class="w"> </span><span class="p">],</span><span class="w">
+ </span><span class="nt">"category_groups"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="s2">"AllHumanUsers"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"AllHeadlessUsers"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"AllMisconfiguredUsers"</span><span class="w">
+ </span><span class="p">],</span><span class="w">
+ </span><span class="nt">"category_regex"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="s2">""</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"^Headless-(.*)"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"^MisconfiguredUser-(.*)"</span><span class="w">
+ </span><span class="p">],</span><span class="w">
+ </span><span class="nt">"profile_name"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"isecpartners"</span><span class="w"> </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<p>This configuration file declares the name of the common IAM group and two lists
+related to the categorization of IAM users:</p>
+
+<ol>
+<li>A list of category groups.</li>
+<li>A list of regular expressions matching our naming convention.</li>
+</ol>
+
+<p><em>Note 1:</em> If you do not have a naming convention in place to distinguish the
+type of user, remove the <em>category_regex</em> attribute from your configuration
+file.</p>
+
+<p><em>Note 2:</em> If a regular expression is only applicable to a subset of category
+groups, you must ensure that both lists have the same length and use an empty
+string for groups that cannot be automatically associated (see the
+<em>AllHumanUsers</em> group in our example).</p>
+
+<p><em>Note 3:</em> Use of a configuration file is not necessary as all values may be
+passed as command line arguments. If a configuration file exists and a value is
+passed as an argument, the value passed via the command line will be used.</p>
+
+<h3>Create your default groups with <em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_default_groups.py">aws_iam_create_default_groups.py</a></em></h3>
+
+<p>The purpose of this tool is to create IAM groups whose name matches the common
+and category groups specified in the above configuration file. Running the
+following command results in four new groups being created if they did not
+already exist.</p>
+<div class="highlight"><pre><code class="language-" data-lang="">./aws_iam_create_default_groups.py --profile isecpartners
+</code></pre></div>
+<h3>(Automatically) sort IAM users with <em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_sort_users.py">aws_iam_sort_users.py</a>.</em></h3>
+
+<p>This tool iterates through all IAM users and attempts to automatically detect
+the IAM groups each user should belong to. For convenience, we recommend adding
+the following to your AWS recipes configuration files:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">"aws_sort_users.py": {
+ "create_groups": false,
+},
+"force_common_group": true
+</code></pre></div>
+<p>This specifies default values for additional arguments to be set when running
+<em>aws_iam_sort_users.py</em>. Specifically, with these values, running this tool
+will automatically add all IAM users to the common group <em>AllUsers</em> and will
+not attempt to create the default groups (not necessary as we already did
+this). Additionally, this tool checks that each IAM user belongs to one of the
+category groups. If this is not the case and the username matches a regular
+expression, the user is automatically added to the matching category group. Otherwise, a
+multi-choice prompt appears to allow manual selection of the appropriate
+category group.</p>
+
+<h3>Additional advantages of configuration files</h3>
+
+<p>Besides helping with simplification of these tools' usage, this new AWS-recipe
+configuration file can be used across tools, allowing for more consistent
+rule enforcement. For example, the
+<em><a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_iam_create_user.py">aws_iam_create_user.py</a>.</em>
+tool uses this configuration file and applies the same business logic to add
+users to the common group and appropriate category group at user creation time. In
+our test environment, for example, running the following command automatically
+added the new user to the <em>MisconfiguredUser</em> group:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_iam_create_user.py --profile isecpartners --users MisconfiguredUser-BlogPostExample
+Creating user MisconfiguredUser-BlogPostExample...
+Save unencrypted value (y/n)? y
+User 'MisconfiguredUser-BlogPostExample' does not belong to the mandatory common group 'AllUsers'. Do you want to remediate this now (y/n)? y
+User 'MisconfiguredUser-BlogPostExample' does not belong to any of the category group (AllHumanUsers, AllHeadlessUsers, AllMisconfiguredUsers). Automatically adding...
+Enabling MFA for user MisconfiguredUser-BlogPostExample...
+</code></pre></div>
+<h3>Conclusion</h3>
+
+<p>While efficient and reliable management of IAM users can be challenging, using
+the right strategy and tools significantly simplifies this process. Creation
+and use of a naming convention for IAM users enables
+automated user management and enforcement of security rules.</p>
+
+ Tue, 09 Jun 2015 09:20:00 -0700
+ http://l01cd3v.github.io/aws/2015/06/09/iam_user_management_2.html
+ http://l01cd3v.github.io/aws/2015/06/09/iam_user_management_2.html
+
+
+
+ Work daily with enforced MFA-protected API access
+ <h3>AWS Security Token Service</h3>
+
+<p>The AWS Security Token Service (STS) is the gateway used to create sessions
+when MFA-protected API access is enabled. This service allows IAM users to
+retrieve short-lived credentials (<em>i.e</em> access key ID, secret access key, and
+session token) in exchange for their long-lived credentials (<em>i.e.</em> AWS access
+key ID and secret key) and their current authentication code. When enforcing
+MFA-protected API access, as recommended in the previous <a href="/aws/2015/04/02/use_and_enforce_mfa.html">Use and enforce
+Multi-Factor
+Authentication</a> post,
+IAM users must use these short-lived credentials to access other AWS services.</p>
+
+<h3>Challenges with MFA-protected API access</h3>
+
+<p>When MFA-protected API access is enforced, managing AWS access keys becomes
+challenging because configuration files that contain these credentials must be
+updated regularly. Users must also ensure that they do not lose their
+long-lived credentials when modifying the configuration files to write their
+short-lived credentials. In order to help with this workflow, iSEC wrote and
+released several simple tools in the
+<a href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a> repository.</p>
+
+<p>The collection of tools that we will discussed below uses the "<a
+target="_blank"
+href="https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs">new
+and standardized way to manage credentials in the AWS SDKs</a>", meaning that
+SDKs are expecting to read credentials from the <em>.aws/credentials</em> file under
+the user's home or profile directory.</p>
+
+<h3>aws_recipes_configure_iam.py</h3>
+
+<p>The
+<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_configure_iam.py">aws_recipes_configure_iam.py</a>
+tool allows users to configure and store their long-lived credentials in a new,
+non-standard, <em>.aws/credentials.no-mfa</em> file. In addition to prompting for the
+AWS access key ID and secret key, this tool also prompts for the MFA device
+serial number because this information must be provided when making calls to
+the STS API. Similar to the AWS CLI and SDKs, it supports profile names. The
+following code snippet is an example of calling this tool to configure a new
+profile called <em>isecpartners</em>:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_configure_iam.py --profile isecpartners
+AWS Access Key ID: AWS_KEY_ID
+AWS Secret Access Key: AWS_SECRET_KEY
+AWS MFA serial: arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
+</code></pre></div>
+<p>When looking at the <em>.aws</em> folder, we can see that a <em>credentials.no-mfa</em> file
+exists and that it contains the credentials that were just entered:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ls -l ~/.aws
+total 4
+-rw-r--r-- 1 loic loic 93 Apr 3 14:00 credentials.no-mfa
+$ cat ~/.aws/credentials.no-mfa
+[isecpartners]
+aws_access_key_id = AWS_KEY_ID
+aws_secret_access_key = AWS_SECRET_KEY
+aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
+</code></pre></div>
+<p>Now that long-lived credentials are configured, we can use the next tool to
+call the AWS STS API and request short-lived credentials that will be used
+to access other AWS services.</p>
+
+<h3>aws_recipes_init_sts_session.py</h3>
+
+<p>The
+<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py">aws_recipes_init_sts_session.py</a>
+tool reads long-lived credentials configured in the .aws/credentials.no-mfa
+file, prompts users for their MFA code, and retrieves STS credentials (AWS
+access key ID, AWS secret key, and session token). The short-lived credentials
+are then saved under the standardized <em>.aws/credentials</em> file to be accessible
+to the AWS CLI and other tools built with the AWS SDKs. The following code
+snippet demonstrates calling this tool to request an STS session token:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ./aws_recipes_init_sts_session.py --profile isecpartners
+Enter your MFA code: 123456
+Successfully configured the session token for profile 'isecpartners'.
+</code></pre></div>
+<p>When looking at the <em>.aws</em> folder, we can see that a standard <em>credentials</em>
+file now exists as well and that it contains the short-lived credentials:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">$ ls -l ~/.aws
+total 8
+-rw-r--r-- 1 loic loic 576 Apr 3 14:14 credentials
+-rw-r--r-- 1 loic loic 179 Apr 3 14:00 credentials.no-mfa
+$ cat ~/.aws/credentials
+[isecpartners]
+aws_access_key_id = STS_KEY_ID
+aws_secret_access_key = STS_SECRET_KEY
+aws_mfa_serial = arn:aws:iam::AWS_ACCOUNT_ID:mfa/USER_NAME
+aws_session_token = AWS//////////SESSION_TOKEN
+</code></pre></div>
+<p>Now that the short-lived credentials are configured, we can use the AWS CLI or
+other tools built with the AWS SDKs that read credentials from this standard
+location. When the STS session expires, users just need to re-run the
+<a href="https://github.com/iSECPartners/AWS-recipes/blob/master/Python/aws_recipes_init_sts_session.py">aws_recipes_init_sts_session.py</a>
+tool and the standard <em>credentials</em> file will be updated with new valid
+short-lived credentials.</p>
+
+<h3>Conclusion</h3>
+
+<p>By using this pair of tools to manage their AWS access keys, IAM users can
+easily use the AWS CLI and other tools built with various AWS SDKs in
+environments that have been secured and enforce MFA-protected API access.</p>
+
+ Fri, 03 Apr 2015 14:10:00 -0700
+ http://l01cd3v.github.io/aws/2015/04/03/session_management_tools.html
+ http://l01cd3v.github.io/aws/2015/04/03/session_management_tools.html
+
+
+
+ Use and enforce Multi-Factor Authentication
+ <h3>What is Multi-Factor Authentication?</h3>
+
+<p>When enabled, Multi-Factor Authentication (MFA) provides strong
+defense-in-depth against compromises of credentials. MFA-enabled users have a
+device that periodically generates a new authentication code (<em>i.e.</em> one-time
+password); they need to enter the current authentication code along with their
+static credentials (<em>i.e.</em> username and password) in order to successfully
+authenticate. In addition to supporting MFA when accessing the web console
+(<em>i.e.</em> password-based authentication), AWS also offers MFA-protected API
+access for users who work with AWS access keys. Through the Security Token
+Service (STS), IAM users can request temporary credentials in exchange for
+their long-lived credentials (<em>i.e.</em> AWS access key ID and secret key) and
+their current authentication code.</p>
+
+<h3>Why should one use and enforce MFA?</h3>
+
+<p>For companies deploying their application in the cloud, a breach that results
+in unauthorized access to the management console — or API — is the
+worst-case scenario. While a number of AWS administrators have realized the
+importance of enabling MFA when they access the web console, a limited number
+of them enforce MFA-protected API access. This represents a huge gap in one's
+security posture because AWS access keys do not come with as many security
+features as passwords do:</p>
+
+<ul>
+<li>AWS administrators can enforce password expiration; this is currently not
+possible for AWS access keys.</li>
+<li>While it is probably safe to assume that most AWS administrators do not store
+their password in plaintext, most of them use AWS access keys. By design, these
+keys are meant to be stored in plaintext files that are accessed by tools built
+with the various AWS SDKs.</li>
+<li>A lost password is a forgotten password; a lost key is a key stored in a lost
+file, which may be on an unencrypted storage device (e.g. hard drive or USB Flash
+drive).</li>
+</ul>
+
+<p>Because AWS access keys are long-lived credentials that are stored in plaintext
+files, they are more susceptible to compromise than passwords. It is therefore
+necessary to enable MFA when the AWS API is accessed using these keys and not
+only when users sign in using their passwords.</p>
+
+<h3>How can one enforce MFA?</h3>
+
+<p>Unfortunately, at time of writing, AWS does not offer an option to enforce
+MFA-protected API access via a global setting. Therefore, AWS account
+administrators must carefully manage their IAM users and develop a strategy to
+reliably achieve this. In order to enforce MFA-protected API access, iSEC
+recommends the following:</p>
+
+<ol>
+<li>Create a common IAM group that all IAM users belong to, as discussed in the previous <a href="/aws/2015/02/24/iam_user_management.html">IAM user management strategy</a> post.</li>
+<li>Add the following policy (also available on <a href="https://github.com/iSECPartners/AWS-recipes/blob/master/IAM-Policies/EnforceMFA-8HourSession.json">Github</a>) to enforce MFA for all users who belong to this group.</li>
+</ol>
+
+<p>This policy will enforce MFA regardless of how the IAM user authenticated with
+AWS; it will be effective whether they use password-based or key-based
+authentication.</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Deny"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Condition"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"Null"</span><span class="p">:{</span><span class="nt">"aws:MultiFactorAuthAge"</span><span class="p">:</span><span class="s2">"true"</span><span class="p">}</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Deny"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Condition"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"NumericGreaterThan"</span><span class="p">:{</span><span class="nt">"aws:MultiFactorAuthAge"</span><span class="p">:</span><span class="s2">"28800"</span><span class="p">}</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<p>The first statement in the above policy denies all actions if the
+<em>aws:MultiFactorAuthAge</em> key is not present; this key only exists if MFA is
+used [1].</p>
+
+<p>The second statement verifies that the validation of the MFA code was performed
+less than eight hours ago. Temporary credentials may be valid for a duration
+between fifteen minutes and thirty-six hours [2]. iSEC recommends requiring
+users to initiate a new session at least once a day.</p>
+
+<p><strong><em>Note:</em></strong> An "explicit deny" means that, regardless of other policies granted
+to a user, this deny rule will prevail. More information about the IAM policy
+evaluation logic can be found in the AWS documentation at <a
+target="_blank"
+href="http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html">http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html</a>.</p>
+
+<h3>Use AWS Scout2 to detect users without MFA</h3>
+
+<p>The default ruleset used by <a href="https://github.com/iSECPartners/Scout2">AWS Scout2</a> includes a rule that checks for IAM users who have password-based authentication enabled but do not have an MFA device configured. If Scout2 detects IAM users with password-based authentication enabled and no MFA device, it will document a "Lack of MFA" security risk in the IAM menu dropdown, as illustrated in the below screenshot.</p>
+
+<p><img src="/images/aws/awsscout2-user-nomfa-1.png" alt="Screenshot: IAM menu dropdown with a "Lack of MFA" security risk"></p>
+
+<p>When clicked, this "Lack of MFA" link filters the list of IAM users to display
+those who have password-based authentication enabled but no MFA device
+configured. The red "No" following "Multi-Factor enabled" indicates a danger
+tied to that particular IAM user.</p>
+
+<p><img src="/images/aws/awsscout2-user-nomfa-2.png" alt="Screenshot: Red "No" indicating that this IAM user may access the web console without MFA"></p>
+
+<h3>How can one use MFA with command line tools?</h3>
+
+<p>Users of the AWS CLI (and other command line tools) have several methods to
+configure their credentials, such as environment variables, configuration
+files, or command line arguments. However, updating these settings on a daily
+basis when MFA-protected API access is enabled is inconvenient. To help
+facilitate this work flow, iSEC has created a set of Python tools and released
+them in the <a href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a>
+repository. Further details about these tools will be published in the next
+blog post.</p>
+
+<p>Additional information about MFA with AWS is available in the AWS
+documentation at <a target="_blank"
+href="https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingMFA.html">
+https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_ManagingMFA.html</a>.</p>
+
+<h3>Conclusion</h3>
+
+<p>Enforcing Multi-Factor Authentication for all IAM users is extremely important
+in order to mitigate the risks of credentials compromise (especially the AWS
+access key ID and secret). This aspect of security is commonly overlooked and
+may result in catastrophic damages. By using a strict strategy for management
+of IAM users and the above IAM policy, AWS administrators may significantly
+reduce risks of account compromise.</p>
+
+<p>[1] <a target="_blank" href="http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_ElementDescriptions.html#AvailableKeys">http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_ElementDescriptions.html#AvailableKeys</a></p>
+
+<p>[2] <a target="_blank" href="http://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html">http://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html</a></p>
+
+ Thu, 02 Apr 2015 14:10:00 -0700
+ http://l01cd3v.github.io/aws/2015/04/02/use_and_enforce_mfa.html
+ http://l01cd3v.github.io/aws/2015/04/02/use_and_enforce_mfa.html
+
+
+
+ IAM user management strategy
+ <h3>Use IAM groups</h3>
+
+<p>When granting privileges to IAM users, AWS account administrators should avoid
+use of user-specific policies. Instead, create groups whose name explicitly
+defines the members' job functions or responsibilities (<em>e.g.</em> AWS
+Administrators, Operations, Developers, Accountants), and define the
+permissions granted within group policies. Doing so will simplify the
+permissions management process as changes in group policies apply to all
+members.</p>
+
+<p>When performing AWS configuration reviews, iSEC often discovers IAM users
+whose privileges have been granted via a combination of IAM user and IAM group
+policies. It is not uncommon to see IAM users who are granted full
+administrator privileges in a redundant manner, via both user and group
+policies. Such configuration creates an avenue for configuration mistakes, as
+another administrator may believe that terminating an IAM user's membership to
+the admin group is sufficient. Therefore, banning use of IAM user policies
+will result in making one's AWS environment less error-prone.</p>
+
+<p><strong><em>Note</em></strong>: It is on purpose that iSEC recommends using IAM group names that
+reflect a job title or responsibility. IAM users who do not fit in such groups
+(<em>e.g.</em> headless users) should not exist. Instead, AWS account administrators
+should investigate use of IAM roles for EC2. Further details will be discussed
+in an upcoming blog post.</p>
+
+<h3>Create a common IAM group to apply generic policies</h3>
+
+<p>Because a number of policies must be applied to all users, iSEC recommends that
+AWS account administrators create an IAM group that all IAM users belong to.
+Doing so will allow AWS account administrators to consistently grant privileges
+and enforce a number of rules.</p>
+
+<p><strong><em>Note</em></strong>: It is important that all IAM users belong to this common IAM group
+to ensure that policies are consistently applied. Failure to do so will create
+gaps in one's AWS environment security posture.</p>
+
+<h3>Authorize IAM users to manage their credentials</h3>
+
+<p>To begin with, iSEC recommends that AWS account administrators allow all of
+their IAM users to manage their credentials, and only theirs. With all IAM
+users belonging to the common IAM group, this can be achieved by applying the
+following IAM policy to the group.</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="s2">"iam:*AccessKey*"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"iam:*Password"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"iam:*MFADevice*"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"iam:UpdateLoginProfile"</span><span class="w">
+ </span><span class="p">],</span><span class="w">
+ </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:iam::AWS_ACCOUNT_ID:user/${aws:username}"</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="w">
+ </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="s2">"iam:CreateVirtualMFADevice"</span><span class="p">,</span><span class="w">
+ </span><span class="s2">"iam:DeleteVirtualMFADevice"</span><span class="w">
+ </span><span class="p">],</span><span class="w">
+ </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:iam::AWS_ACCOUNT_ID:mfa/${aws:username}"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<p>While the above policy is sufficient to allow users to manage their
+credentials, AWS administrators may consider the following statement as an
+addition; it allows IAM users to know what the account's password policy is.</p>
+<div class="highlight"><pre><code class="language-" data-lang=""><span class="p">{</span><span class="w">
+ </span><span class="nt">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"iam:GetAccountPasswordPolicy"</span><span class="p">,</span><span class="w">
+ </span><span class="nt">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></code></pre></div>
+<h3>Use AWS Scout2 to detect user policies</h3>
+
+<p>The default ruleset used by <a href="https://github.com/iSECPartners/Scout2">AWS
+Scout2</a> includes a rule that checks for
+user policies and reports the use of user-specific IAM policies as a warning.
+Detection of user-specific IAM policies results in the IAM menu dropdown
+containing a "User policies" security risk, as illustrated in the below screenshot.</p>
+
+<p><img src="/images/aws/awsscout2-iam-user-policy-1.png" alt="Screenshot: IAM menu dropdown with a User policies security risk"></p>
+
+<p>When clicked-on, this "User policies" link filters the list of IAM users to only
+display those who have at least one user policy attached. The orange badge
+indicates a warning and the count of user policies attached to this particular
+IAM user.</p>
+
+<p><img src="/images/aws/awsscout2-iam-user-policy-2.png" alt="Screenshot: Orange badge indicating that at least one user policy is attached to that IAM user"></p>
+
+<h3>Check that all IAM users belong to the common group</h3>
+
+<p>AWS Scout2 comes with a tool — RulesGenerator.py — that allows AWS account
+administrators to generate a custom ruleset to tailor the report to their
+needs. An optional IAM rule requires all IAM users to belong to a common IAM
+group. In order to enable this rule, the following can be done:</p>
+
+<ol>
+<li>Run the rules generator with the following command line:
+<pre style="margin-left: -20px; margin-top: 10px; margin-bottom: 10px"><code>./RulesGenerator.py --ruleset_name isec --services iam</pre></code></li>
+<li>Answer "yes" to the question "Would you like to ensure that all IAM users belong to a given IAM group?"</li>
+<li>Enter the name of your common group (<em>e.g.</em> AllUsers)</li>
+<li>Enter "yes" or "y" to confirm</li>
+<li>Change the level if desired</li>
+<li>Run Scout2</li>
+</ol>
+
+<p><strong><em>Note</em></strong>: If you have already run Scout2 and do not wish to download the latest
+IAM configuration, use the following command to run an offline analysis:</p>
+<div class="highlight"><pre><code class="language-" data-lang="">./Scout2.py --ruleset_name isec --services iam --local
+</code></pre></div>
+<p>The following screenshot illustrates the IAM menu dropdown containing a
+security risk when IAM users do not belong to the configured common group.</p>
+
+<p><img src="/images/aws/awsscout2-iam-user-commongroup-1.png" alt="Screenshot: IAM menu dropdown when IAM users do not belong to the common group"></p>
+
+<p>When clicked-on, this link filters the list of IAM users to only display those
+who do not belong to the common IAM group. A colored warning sign appears,
+warning about this issue.</p>
+
+<p><img src="/images/aws/awsscout2-iam-user-commongroup-2.png" alt="Screenshot: Orange badge indicating that at least one user policy is attached to that IAM user"></p>
+
+<h3>Conclusion</h3>
+
+<p>Strict management of IAM users and tight control of their privileges is key in
+maintaining a secure AWS environment. When followed, the above recommendations
+should enable AWS administrators to manage IAM users with improved efficiency
+and lower the chances of overly privileged users to exist.</p>
+
+ Tue, 24 Feb 2015 20:49:00 -0800
+ http://l01cd3v.github.io/aws/2015/02/24/iam_user_management.html
+ http://l01cd3v.github.io/aws/2015/02/24/iam_user_management.html
+
+
+
+ Do not use your AWS root account
+ <h3>What is the AWS root account?</h3>
+
+<p>The AWS root account is the account that was used -- or created -- when signing
+up with Amazon Web Services. This account has full access to all resources in
+the account and it is not possible to alter this configuration.</p>
+
+<h3>Risks of using the AWS root account</h3>
+
+<p>Using the AWS root account means that there is potential for its compromise.
+In particular, iSEC noticed that AWS customers who use the AWS root account
+tend to do the following:</p>
+
+<ol>
+<li>Share credentials between employees.</li>
+<li>Disable Multi-Factor Authentication (MFA) for convenience.</li>
+</ol>
+
+<p>Shared credentials, aside from increasing the risk of compromise during the
+sharing process, render credential rotation impractical due to the need for the
+newly-generated secret to be known by multiple parties. Sharing the AWS root
+account also undermines any effort towards using IAM and leveraging the
+fine-grained access controls it offers. Finally, shared credentials result in
+loss of the attribution ability, which makes auditing harder and may prevent
+successful investigation.</p>
+
+<h3>AWS Identity and Access Management (IAM)</h3>
+
+<p>AWS IAM allows account administrators to create users for every employee and
+grant them access to a limited set of services, actions, and resources. This
+allows AWS account administrators to apply the principle of least privilege,
+which dictates that a given user should only be able to access the information
+and resources that are necessary for them to perform tasks they are responsible
+for. Additionally, use of IAM allows AWS users to rotate credentials and revoke
+privileges without impacting other employees.</p>
+
+<p>AWS account administrators should create an <em>Administrator</em> IAM group, grant
+administrator privileges to this group, and create individual IAM users for
+each employee in charge of administrating the AWS account. When done, the AWS
+root password should be rotated and stored in a safe manner. Furthermore,
+additional credentials such as access keys and certificates should be deleted.</p>
+
+<h3>Important security consideration about the root account</h3>
+
+<p>AWS users should always enable MFA on their root account, even when the
+password is securely stored; it is important to realize that the password reset
+for the root account process only requires access to the email address
+associated with this account. <strong>This means that, without MFA, your production
+environment is only as secure as an email.</strong></p>
+
+ Mon, 23 Feb 2015 08:42:00 -0800
+ http://l01cd3v.github.io/aws/2015/02/23/do_not_use_your_root_account.html
+ http://l01cd3v.github.io/aws/2015/02/23/do_not_use_your_root_account.html
+
+
+
+ Announcing the AWS blog post series
+ <p>Starting this month, iSEC Partners will start a series of blog posts related to
+AWS. The goal of these blog posts will be to:</p>
+
+<ul>
+<li>Discuss common security gaps in AWS environments</li>
+<li>Discuss common security gaps in the architecture of applications deployed in
+the cloud</li>
+<li>Describe methods and tools used to identify these security gaps</li>
+<li>Share tools and scripts that facilitate daily and secure work with AWS</li>
+<li>Share AWS policies that help improve the security posture of AWS environments</li>
+</ul>
+
+<p>To share material, iSEC created a new public
+<a target="_blank"
+href="https://github.com/iSECPartners/AWS-recipes">AWS-recipes</a> repository
+on Github. The tools and policies shared in this repository will be discussed
+and explained in dedicated blog articles.</p>
+
+<p>Because iSEC has been assessing the security of AWS environment for several
+years, we have a number of ideas and articles in the pipe awaiting to be
+written and published. Our target goal is to publish at least on a bi-monthly
+basis at the beginning of the project, and adjust this publication rate after
+we catch up.</p>
+
+<p>Without further due, we will start this series with articles that discuss
+Identity and Access Management (IAM) common issues and best practices, and will
+present a strategy to improve one's security posture when using AWS.</p>
+
+ Sun, 22 Feb 2015 22:24:00 -0800
+ http://l01cd3v.github.io/aws/2015/02/22/announcing_the_aws_blog_post_series.html
+ http://l01cd3v.github.io/aws/2015/02/22/announcing_the_aws_blog_post_series.html
+
+
diff --git a/index.html b/index.html
index ca8a54e..56bdb54 100644
--- a/index.html
+++ b/index.html
@@ -1,45 +1,845 @@
----
-layout: default
----
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ l01cd3v.github.io
+
-
+
+
+
+
+
l01cd3v.github.io
+
by Loïc
+
+
+
+
+
- {% for post in paginator.posts %}
+
- {% include post_body.html %}
+
- {% if forloop.last %}
- {% comment %} No separator {% endcomment %}
- {% else %}
+
+
+
Last Tuesday (August 3rd), I presented "Access Keys Will Kill You Before You
+Kill The Password" at Black Hat US 2016. The summary is on the Black
+Hat website and the updated slide deck is available Here.
+This presentation aimed at highlighting risks associated with usage of AWS API
+access keys in environments that do not enforce MFA-protected API access, and
+documented strategies and IAM policies to help address these risks.
+
+
On Wednesday (August 4th), I presented Scout2 at Black Hat Arsenal. During two
+hours, I had the opportunity to demo Scout2 and meet users of the tool who
+shared valuable feedback with me. I look forward to implementing some of the
+features discussed during this event, including adding support for ECS and
+finishing the new rules generator.
+
+
As a reminder, Scout2 is available on Github, feedback is appreciated,
+and feature requests and pull requests are welcome. The Scout2 documentation is
+available at https://nccgroup.github.io/Scout2.
A significant challenge for companies using the cloud lies in ensuring that
+their firewall rules follow the principle of least privilege. It is
+extremely common nowadays to delegate management of security groups to developers, for
+both production and test environments. This means that security groups and
+their associated rules are managed by a much larger number of employees than
+what used to be the case in non-cloud environments, where a unique, smaller
+team was in charge of managing all firewall rules. Due to the more dynamic
+nature of cloud-based infrastructures, companies should review their cloud
+environment's firewall rules on a more frequent basis than for non cloud-based
+systems. Unfortunately, this is a difficult exercise due to the large number of
+CIDRs that may be whitelisted in a given AWS account. Keeping track of all
+known CIDRs and what hosts or networks they represent is not easy for
+employees, and is almost impossible for external auditors who must perform the
+review within a limited timeframe.
+
+
In this post, I will document how this issue can be addressed using the
+AWS-Recipes tools and
+Scout2.
+
+
Feed custom ip-ranges files to Scout2
+
+
Today, I am excited to announce that Scout2 accepts JSON files that
+contain known CIDRs along with arbitrary metadata such as the host or network
+they represent. When provided with such files, Scout2's report displays the
+"friendly name" of each known CIDR that is whitelisted in security group rules.
+This means that, instead of reviewing a list of obscure IP ranges, users of
+Scout2 may now rely on the name associated with each CIDR.
+
+
In order to use this new feature, Scout2 should be run with the following
+arguments:
+
./Scout2.py --profile nccgroup --ip-ranges ip-ranges-nccgroup.json ip-ranges-ncc-offices.json --ip-ranges-key-name name
+
+
In the above command line, Scout2 receives two ip-ranges JSON files via the
+"--ip-ranges" argument:
+
+
+
ip-ranges-nccgroup.json, which contains the public IP addresses in the AWS IP space in use
+
ip-ranges-ncc-offices.json, which contains the public IP addresses of several offices
+
+
+
Furthermore, the "--ip-ranges-key-name" argument indicates which JSON field to
+display as the "friendly name".
+
+
The following screenshot illustrates that, in the Scout2 report, the name of
+each known CIDR is displayed. When an IP which belongs to a known CIDR is
+whitelisted, the name of the corresponding CIDR is used. In this example,
+5.5.5.42/32 belongs to the 5.5.5.0/24 CIDR, which is associated with the "San
+Francisco" office. An "Unknown CIDR" value is displayed when an unknown value
+is whitelisted.
+
+
+
+
The next section of this blog post documents how users can create and manage
+these ip-ranges JSON files.
+
+
Manage known CIDRs with aws_recipes_create_ip_ranges.py
Automatically create ip-ranges files based on public IP addresses in AWS (Elastic IPs and EC2 instances)
+
Automatically create ip-ranges files based on IP addresses documented in a CSV file
+
Manually create and manage ip-ranges files
+
+
+
Each of these use cases is detailed in an example below, with detailed input,
+commands, and output contents.
+
+
Note: In the commands below, the "--debug" argument is used to
+output pretty-printed JSON, for documentation purposes.
+
+
Automatically create ip-ranges based on public IP addresses in an AWS account
+
+
First, this tool may be used to create an ip-ranges file that contains an AWS
+account's elastic IP addresses and EC2 instances' public IP addresses. By doing
+so, AWS users will be able to maintain a list of public IP addresses in the AWS
+IP space that are associated with their resources. Assuming that AWS
+credentials are configured under the "nccgroup" profile name, the command
+below may be used:
+
$ ./aws_recipes_create_ip_ranges.py --profile nccgroup --debug
+
+Fetching public IP information for the 'nccgroup' environment...
+...in us-east-1: EC2 instances
+...in us-east-1: Elastic IP addresses
+...in ap-northeast-1: EC2 instances
+...in ap-northeast-1: Elastic IP addresses
+...in eu-west-1: EC2 instances
+...in eu-west-1: Elastic IP addresses
+...in ap-southeast-1: EC2 instances
+...in ap-southeast-1: Elastic IP addresses
+...in ap-southeast-2: EC2 instances
+...in ap-southeast-2: Elastic IP addresses
+...in us-west-2: EC2 instances
+...in us-west-2: Elastic IP addresses
+...in us-west-1: EC2 instances
+...in us-west-1: Elastic IP addresses
+...in eu-central-1: EC2 instances
+...in eu-central-1: Elastic IP addresses
+...in sa-east-1: EC2 instances
+...in sa-east-1: Elastic IP addresses
+
+
My test environment has one elastic IP address that is not associated
+with an AWS resource, and one EC2 instance that has a non-elastic public IP.
+Executing the above command results in the creation of an
+"ip-ranges-nccgroup.json" file that has the following contents:
From experience, I know that many companies maintain a list of their
+public IP addresses, along with other network configuration information, in alternate formats, such as CSV. In
+order to help with the conversion, the tool supports reading CIDR information
+from CSV files. The tool was designed to be flexible and allow the creation of IP
+ranges from any CSV file. In this blog post, I provide two examples.
+
+
This first example demonstrates how to use the tool to build a JSON file based
+on the CSV column headers. Only attributes specified on the command line will
+be copied over.
+
+
Contents of test1.csv:
+
ip_prefix, discarded_value, name
+4.4.4.0/24, ncc group, NY office
+# This is a comment...
+5.5.5.0/24, ncc group, Seattle office
+
+
Command line to convert the contents of the CSV file into JSON:
+
./aws_recipes_create_ip_ranges.py --csv-ip-ranges test1.csv --attributes ip_prefix name --profile ncc-test1 --debug
+
The second example demonstrates how to use the tool to parse a CSV file with
+custom column names and separate columns for the base IP and subnet mask. The
+"--mappings" argument determines how columns will be mapped to the JSON
+file's attributes.
+
+
Contents of test2.csv
+
Base IP, Dotted Subnet Mask, Subnet Mask, Something, Name, Something else
+3.3.3.0, 255.255.255.0, /24, Value to discard, SF Office, Other value to discard
+
+
Command line to convert the contents of the CSV file into JSON:
In case CIDRs were not managed in a CSV file, the tools offers an interactive
+mode that may be leveraged to manually create a JSON ip-ranges file. The
+following snippet illustrates how to use the tool to interactively create new
+ip-ranges JSON files:
+
$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name
+
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+5.5.5.0/24
+You entered "5.5.5.0/24". Is that correct (y/n)?
+y
+Enter the 'name' value:
+San Francisco
+You entered "San Francisco". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+6.6.6.6/32
+You entered "6.6.6.6/32". Is that correct (y/n)?
+y
+Enter the 'name' value:
+San Francisco
+You entered "San Francisco". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+n
+
The tool can also automatically add new CIDRs to existing ip-ranges files:
+
$ ./aws_recipes_create_ip_ranges.py --interactive --profile ncc-offices --attributes name --debug
+
+Loading existing IP ranges from ip-ranges-ncc-offices.json
+Add a new IP prefix to the ip ranges (y/n)?
+y
+Enter the new IP prefix:
+7.7.7.7/32
+You entered "7.7.7.7/32". Is that correct (y/n)?
+y
+Enter the 'name' value:
+Seattle
+You entered "Seattle". Is that correct (y/n)?
+y
+Add a new IP prefix to the ip ranges (y/n)?
+n
+File 'ip-ranges-ncc-offices.json' already exists. Do you want to overwrite it (y/n)?
+y
+
+$ cat ip-ranges-ncc-offices.json
+{
+ "createDate": "2015-11-16-22-44-38",
+ "prefixes": [
+ {
+ "ip_prefix": "5.5.5.0/24",
+ "name": "San Francisco"
+ },
+ {
+ "ip_prefix": "6.6.6.6/32",
+ "name": "San Francisco"
+ },
+ {
+ "ip_prefix": "7.7.7.7/32",
+ "name": "Seattle"
+ }
+ ]
+}
+
+
Conclusion
+
+
This addition to Scout2 provides AWS account administrators and auditors with
+an improved insight into their environment. Usage of this feature should result
+in further hardened security groups because detection of unknown whitelisted
+CIDRs and understanding of existing rules is significantly easier.
+
+
I am currently working on a major rework of Scout2's reporting engine,
+which will further improve reporting and allow creation of new alerts when an
+unknown CIDR is whitelisted.
Today, I am excited to announce that support for Redshift was added in
+Scout2. By default, Scout2 will fetch information about your Redshift clusters,
+cluster parameter groups, and cluster security groups if you still use
+EC2-Classic. At this stage, Scout2 comes with six Redshift security rules that
+are enabled by default:
+
+
+
Clusters
+
+
+
Check whether version upgrade is enabled
+
Check whether the cluster is publicly accessible
+
Check whether database encryption is enabled
+
+
Cluster parameter groups
+
+
+
Check whether SSL/TLS is required to access the database
+
Check whether user activity logging is enabled
+
+
Cluster security groups (EC2-classic)
+
+
+
Check whether the security group allows access to all IP addresses (0.0.0.0/0)
+
+
+
+
Scout2 was first released over a year and a half ago, and proved to be extremely
+helpful when performing AWS configuration reviews. While
+Scout2's initial release only supported three services (IAM, EC2, and S3) and
+included thirteen security checks, the tool rapidly grew to add support for RDS
+and CloudTrail. Furthermore, the tool now offers over fifty tests throughout
+these five supported services. I hope that support for Redshift will bring
+value to users of Scout2, and welcome feature requests, bug reports, and
+recommendations on Github at
+https://github.com/iSECPartners/Scout2/issues.
With boto3 being stable and generally available1, I took the opportunity
+to migrate Scout2 and AWS-recipes to boto3. As part of that migration
+effort, I decided to publish the formerly-known-as AWSUtils repository -- used
+by Scout2 and AWS-recipes -- as a python package required by these tools,
+rather than requiring users to work with Git submodules. I've also added more
+flexibility when working with MFA-protected API calls and improved versioning
+across the project.
+
+
opinel
+
+
To avoid name conflicts, I decided to rename the shared AWSUtils code to a
+less misleading name: opinel. The opinel package is published on PyPI, and thus can
+be installed using pip and easy_install. The corresponding source code is still
+open-sourced on Github at https://github.com/iSECPartners/opinel.
+As a result, Scout2 and AWS-recipes have been modified to list opinel as a
+requirement, which significantly simplifies installation and management of this
+shared code.
+
+
Support for Python 2.7 and 3.x
+
+
Because boto3 supports both Python2 and Python3, I decided to make sure that
+the code built on top of that package has similar properties. As a result,
+the latest versions of Scout2 and AWS-recipes support Python 2.7 and 3.x.
+Note that opinel will NOT work with Python 2.6.
+
+
Modification of the MFA workflow
+
+
As requested by a user of AWS-recipes2, I modified the workflow when
+using MFA-protected API access to no longer store the long-lived credentials
+in a separate file. As a result, the .aws/credentials.no-mfa file is no
+longer supported and all credentials are stored in the standard AWS credentials
+file under .aws/credentials. Usage of the existing tools remains unchanged,
+but the long-lived credentials are now accessible via a new profile name:
+profile_name-nomfa. This allows users to work with both STS and long-lived
+credentials if need be.
+
+
If you already had configured your environment to work with MFA-protected API
+access, you will need to copy your long-lived credentials back to the
+.aws/credentials file. This can be done with a simple command such as the
+following:
+
cat ~/.aws/credentials.no-mfa | sed -e 's/]$/-nomfa]/g' >> ~/.aws/credentials
+
+
Support to use assumed-role credentials
+
+
With this new workflow implemented, I created a new recipe that allows
+configuration of role-credentials in the .aws/credentials file. When the following
+command is run, it uses the credentials associated with the isecpartners
+profile to request role credentials for the IAM-Scout2 role. The role
+credentials are then written in the .aws/credentials file in a new profile
+named isecpartners-Scout2, which is the profile name appended by the role
+session name.
Users can then use their favorite tools that support profiles. For example,
+Scout2 could be run with the following command line:
+
$ ./Scout2.py --profile isecpartners-Scout2
+
+
Note that this recipe supports MFA if the assumed role requires it:
+
+
+
If you never configured your environment to work with MFA, you can provide your MFA serial number (ARN) and current token code as arguments.
+
If you already configured your environment to work with MFA and stored your MFA serial in the .aws/credentials file, you just need to pass your token code as an additional argument.
+
Finally, if you already initiated an STS session, you do not need to provide a new token code and can run the command as above.
+
+
+
Conclusion
+
+
With the release of opinel, I hope to simplify distribution and management of
+the code shared between Scout2 and AWS-recipes. Additionally, I
+significantly modified the workflow and credentials storage when working with
+MFA-protected API calls, which allows users to use both their long-lived and STS
+credentials.
The previous IAM user management strategy post discussed how
+usage of IAM groups enables AWS administrators to consistently grant privileges
+and enforce a number of security rules (such as MFA-protected API access). This
+blog post will build on this idea by introducing category groups and
+documenting new tools to improve IAM user management.
+
+
Categorize your IAM users
+
+
For a variety of reasons, applying a single set of security rules to all IAM
+users is not always practical. For example, because many applications running
+in AWS predate IAM roles, numerous environments still rely on the existence of
+headless IAM users. Additionally, third parties may be granted access to an AWS
+account for a number of reasons but may not be able to comply with the same set
+of security rules that employees follow. For this reason, NCC recommends using
+category groups to sort IAM users and reliably enforce appropriate security
+measures. For example, one group for all human users and a second for all headless users may be
+created: MFA-protected API access and password management are not relevant for
+headless users. Furthermore, human users may be categorized into several groups
+such as employees and contractors: API access can be restricted to the
+corporate IP range for employees but might not be achievable for contractors.
+
+
Note 1: The set of category groups should define all types of IAM users that
+may exist in your AWS account and each IAM user should belong to one -- and
+only one -- category group (they may belong to other groups though).
+
+
Note 2: The common group and category groups should be used to enable enforcing
+security in one's AWS environment. Policies attached to these groups should be
+carefully reviewed and grant the minimum set of privileges necessary for this
+type of IAM user (e.g. credential management for humans).
+
+
Example of category groups
+
+
The rest of this article describes a number of tools developed and used by
+NCC to help implement this IAM user management strategy. These tools can be found
+in the AWS-Recipes repository. We will
+use our test AWS environment as an example, in which we use three category groups in
+addition to the AllUsers common group:
+
+
+
AllHumans, the group all employees must belong to.
+
AllHeadlessUsers, the group all headless IAM users must belong to.
+
AllMisconfiguredUsers, a placeholder for sample misconfigured users.
+
+
+
We also have an IAM user naming convention that requires usernames to match the
+following schema:
+
+
+
Employees: firstname initial appended with lastname
+
Headless user: name of the service prefixed with HeadlessUser-
+
Misconfigured: description of the misconfiguration prefixed with MisconfiguredUser-
+
+
+
Based on these rules, we created a configuration file stored under
+.aws/recipes/isecpartners.json, with isecpartners matching the profile's
+name. If you do not use profiles, the configuration will be under
+.aws/recipes/default.json.
This configuration file declares the name of the common IAM group and two lists
+related to the categorization of IAM users:
+
+
+
A list of category groups.
+
A list of regular expressions matching our naming convention.
+
+
+
Note 1: If you do not have a naming convention in place to distinguish the
+type of user, remove the category_regex attribute from your configuration
+file.
+
+
Note 2: If a regular expression is only applicable to a subset of category
+groups, you must ensure that both lists have the same length and use an empty
+string for groups that cannot be automatically associated (see the
+AllHumanUsers group in our example).
+
+
Note 3: Use of a configuration file is not necessary as all values may be
+passed as command line arguments. If a configuration file exists and a value is
+passed as an argument, the value passed via the command line will be used.
The purpose of this tool is to create IAM groups whose name matches the common
+and category groups specified in the above configuration file. Running the
+following command results in four new groups being created if they did not
+already exist.
This tool iterates through all IAM users and attempts to automatically detect
+the IAM groups each user should belong to. For convenience, we recommend adding
+the following to your AWS recipes configuration files:
This specifies default values for additional arguments to be set when running
+aws_iam_sort_users.py. Specifically, with these values, running this tool
+will automatically add all IAM users to the common group AllUsers and will
+not attempt to create the default groups (not necessary as we already did
+this). Additionally, this tool checks that each IAM user belongs to one of the
+category groups. If this is not the case and the username matches a regular
+expression, the user is automatically added to the matching category group. Otherwise, a
+multi-choice prompt appears to allow manual selection of the appropriate
+category group.
+
+
Additional advantages of configuration files
+
+
Besides helping with simplification of these tools' usage, this new AWS-recipe
+configuration file can be used across tools, allowing for more consistent
+rule enforcement. For example, the
+aws_iam_create_user.py.
+tool uses this configuration file and applies the same business logic to add
+users to the common group and appropriate category group at user creation time. In
+our test environment, for example, running the following command automatically
+added the new user to the MisconfiguredUser group:
+
$ ./aws_iam_create_user.py --profile isecpartners --users MisconfiguredUser-BlogPostExample
+Creating user MisconfiguredUser-BlogPostExample...
+Save unencrypted value (y/n)? y
+User 'MisconfiguredUser-BlogPostExample' does not belong to the mandatory common group 'AllUsers'. Do you want to remediate this now (y/n)? y
+User 'MisconfiguredUser-BlogPostExample' does not belong to any of the category group (AllHumanUsers, AllHeadlessUsers, AllMisconfiguredUsers). Automatically adding...
+Enabling MFA for user MisconfiguredUser-BlogPostExample...
+
+
Conclusion
+
+
While efficient and reliable management of IAM users can be challenging, using
+the right strategy and tools significantly simplifies this process. Creation
+and use of a naming convention for IAM users enables
+automated user management and enforcement of security rules.
+
+
+
+
+
+
+
+
diff --git a/_site/page2/index.html b/page2/index.html
similarity index 100%
rename from _site/page2/index.html
rename to page2/index.html
diff --git a/_site/page3/index.html b/page3/index.html
similarity index 100%
rename from _site/page3/index.html
rename to page3/index.html
diff --git a/_site/projects/index.html b/projects/index.html
similarity index 100%
rename from _site/projects/index.html
rename to projects/index.html
diff --git a/projects/index.md b/projects/index.md
deleted file mode 100644
index 848cdcd..0000000
--- a/projects/index.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-layout: default
----
-
-# Projects
-
-## Cloud Security
-
-### AWS Scout2
-
-Scout2 is a security tool designed to assist security assessments of AWS
-environments. It is written in Python and uses boto (AWS SDK for Python) to
-gather security-related information for several services such as IAM, EC2, and
-S3. The tool is open-source and available on Github at
-https://github.com/iSECPartners/Scout2.
-
-### AWS Recipes
-
-The AWS-recipes repository is a placeholder for the following:
-
-* Tools that facilitate daily work with AWS in a secure manner
-* Tools that may help penetration testers who compromise an AWS access key
-* IAM policies that improve one's security posture
-
-Most tools available are written in Python, but I do not exclude using other
-SDKs or the CLI tool sometimes. All tools, techniques, and policies are
-discussed in the [AWS blog post series]({{ site.baseurl}}/categories/aws). The
-AWS recipes repository is available at https://github.com/iSECPartners/AWS-recipes.
-
-### AWS Utils
-
-AWS Utils is a Python library shared between Scout2 and tools provided in AWS
-recipes. It is used as a git module in both repositories to allow code reused
-accross projects. This library is open-source as well and is available on Github at
-https://github.com/iSECPartners/AWSUtils.
-
-## Privacy
-
-### CookieJar
-
-CookieJar is a browser extension for Chrome and Opera that strips cookies out
-of HTTP requests when the root domain of the target URL does not match the root
-domain of the tab's URL. It has the effect of anonymizing all "silent" requests
-that are sent to third parties (_e.g._ social networks) when you browse the
-web. The source code is open-source and available on Github at https://github.com/l01cd3v/CookieJar.
-The released extensions are available for free in each browser's extension
-store:
-
-* Chrome : https://chrome.google.com/webstore/detail/cookie-jar/iikhngeniebocgncjooahpaojhnonkfb
-* Opera : https://addons.opera.com/en/extensions/details/cookie-jar
diff --git a/_site/research/index.html b/research/index.html
similarity index 100%
rename from _site/research/index.html
rename to research/index.html
diff --git a/research/index.md b/research/index.md
deleted file mode 100644
index c455d5c..0000000
--- a/research/index.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-layout: default
----
-
-# Research
-
-## AWS blog post series
-
-Starting February 2015, I started a series of blog posts about security in the
-AWS Cloud. Each post is originally published on the iSEC Partners blog at
-https://isecpartners.github.io and re-posted here. All
-these posts are indexed in the [AWS Category
-page]({{site.baseurl}}/categories/aws).
diff --git a/slides/index.html b/slides/index.html
index 21bdad7..77eb8c2 100644
--- a/slides/index.html
+++ b/slides/index.html
@@ -1,19 +1,89 @@
----
-layout: default
----
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ l01cd3v.github.io
+
-