Skip to content

Commit

Permalink
add encryption support (#22)
Browse files Browse the repository at this point in the history
* add support for encrypting key pair before sending it to the user

* update permission of destructor lambda and delete ssm param upon key destruction

* add function to delete ssm parameter

* update helper script and remove template_file dependency

* multiple updates

* add helper script to decrypt cipher

* multiple updates

* fix permission and variable value type

* update github labels

* add checkov skip statements

* update readme

* update logic flow in readme and diagram

* udpate readme

* comment pull request trigger for semgrep

* modify semgrep config as per official doc

* use action rather than container for semgrep

* add semgrepignore file
  • Loading branch information
paliwalvimal authored Apr 5, 2023
1 parent cf92e05 commit 7f268fb
Show file tree
Hide file tree
Showing 16 changed files with 414 additions and 171 deletions.
24 changes: 14 additions & 10 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: semgrep

on:
# Scan changed files in PRs, block on new issues only (existing issues ignored)
pull_request:
branches: [ main ]
# pull_request:
# branches: [ main ]

# Scan all files on branches, block on any issues
push:
Expand All @@ -15,26 +15,30 @@ on:
# schedule:
# - cron: '30 0 1,15 * *' # scheduled for 00:30 UTC on both the 1st and 15th of the month

permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results

defaults:
run:
working-directory: src

jobs:
semgrep:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
name: scan
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
# Skip any PR created by dependabot to avoid permission issues
if: (github.actor != 'dependabot[bot]')
steps:
# Fetch project source
- uses: actions/checkout@v3

- run: semgrep ci --config "p/ci" --config "p/python" --config "p/owasp-top-ten" --sarif --output=semgrep.sarif
- uses: returntocorp/semgrep-action@v1
with:
generateSarif: "1"
config: >-
p/ci
p/python
p/owasp-top-ten
p/cwe-top-25
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
Expand Down
1 change: 1 addition & 0 deletions .semgrepignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform/
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ This tool generates a new IAM access key pair every X number of days and informs
![aws-iam-key-rotator](iam-key-rotator.jpeg "AWS IAM Key Rotator")

- CloudWatch triggers lambda function which checks the age of access key for all the IAM users who have **IKR:EMAIL**(case-insensitive) tag attached.
- If existing access key age is greater than `ACCESS_KEY_AGE` environment variable or `IKR:ROTATE_AFTER_DAYS` tag associated to the IAM user and if the user ONLY has a single key pair associated a new key pair is generated and the same is mailed to the user via your selected mail service.
- The existing access key is than stored in DynamoDB table with user details and an expiration timestamp.
- DynamoDB stream triggers destructor lambda function which is responsible for deleting the old access key associated to IAM user if the stream event is `delete`.
- In case it fails to delete the existing key pair the entry is added back to the DynamoDB table so that the same can be picked up later for retry.
- If existing access key age is greater than `ACCESS_KEY_AGE` environment variable or `IKR:ROTATE_AFTER_DAYS` tag associated to the IAM user and if the user ONLY has a single key pair associated, a new key pair is generated and if `ENCRYPT_KEY_PAIR` environment variable is set to true the new key pair is encrypted using a symmetric key which is stored in SSM parameter (`/ikr/secret/iam/IAM_USERNAME`) before the same is mailed to the user via the selected mail service.
- The existing access key is then stored in DynamoDB table with user details and an expiration timestamp.
- DynamoDB stream triggers destructor lambda function which is responsible for deleting the old access key associated to IAM user and the SSM parameter that stores the symmetric encryption key if `ENCRYPT_KEY_PAIR` environment variable is set to true. The destruction operation is carried out only if the DynamoDB stream event is of type `delete`.
- In case the destructor function fails to delete the existing key pair, the entry is added back to the DynamoDB table for retry.

### Setup:
- Use the [terraform module](terraform) included in this repo to create all the AWS resources required to automate IAM key rotation
Expand All @@ -41,3 +41,4 @@ This tool generates a new IAM access key pair every X number of days and informs

### Helper Script:
- `tag-iam-users.py`: Tags IAM users by reading **iam-user-tags.json** file
- `decryption.py`: Decrypt cipher text using the encryption key stored in the SSM parmeter store
15 changes: 15 additions & 0 deletions decryption.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import os

from cryptography.fernet import Fernet

ENC_KEY = os.environ.get('ENC_KEY', None)
CIPHER_TEXT = os.environ.get('CIPHER_TEXT', None)

if ENC_KEY is None:
raise KeyError('ENC_KEY is required to decrypt the cipher text')

if CIPHER_TEXT is None:
raise KeyError('CIPHER_TEXT is required')

f = Fernet(ENC_KEY)
print(f.decrypt(CIPHER_TEXT.encode('utf-8')).decode('utf-8'))
125 changes: 124 additions & 1 deletion iam-key-rotator.drawio
Original file line number Diff line number Diff line change
@@ -1 +1,124 @@
<mxfile host="Electron" modified="2021-06-03T05:34:09.166Z" agent="5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.6.13 Chrome/89.0.4389.128 Electron/12.0.7 Safari/537.36" etag="4mfJHJVs-9AIu1A0B5z_" version="14.6.13" type="device"><diagram id="9zp9oJUibIssuBAXWE32" name="Page-1">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</diagram></mxfile>
<mxfile host="Electron" modified="2023-04-04T21:36:39.528Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.1.2 Chrome/106.0.5249.199 Electron/21.4.3 Safari/537.36" etag="IZNVAtsaUwbHOiNjfb5G" version="21.1.2" type="device">
<diagram id="9zp9oJUibIssuBAXWE32" name="Page-1">
<mxGraphModel dx="1306" dy="809" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="BnlXlSoju1qgPTf3SqZH-29" value="" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.rect;fillColor2=none;strokeWidth=1;size=20;indent=5;strokeColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="130" y="146" width="911" height="362" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-2" value="CloudWatch Event" style="outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#BC1356;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.event_time_based;" parent="1" vertex="1">
<mxGeometry x="150" y="280" width="78" height="78" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-9" value="DynamoDB" style="points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;gradientColor=#4D72F3;gradientDirection=north;fillColor=#3334B9;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.dynamodb;" parent="1" vertex="1">
<mxGeometry x="690" y="160" width="78" height="78" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-10" value="IAM Users" style="points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;gradientColor=#F54749;gradientDirection=north;fillColor=#C7131F;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.identity_and_access_management;labelPosition=center;" parent="1" vertex="1">
<mxGeometry x="690" y="280" width="78" height="78" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-14" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="BnlXlSoju1qgPTf3SqZH-11" target="BnlXlSoju1qgPTf3SqZH-10" edge="1">
<mxGeometry x="129" y="148" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-20" value="Scan IAM users who have&lt;br&gt;access keys older than&lt;br&gt;X days" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-14" vertex="1" connectable="0">
<mxGeometry x="-0.1601" y="1" relative="1" as="geometry">
<mxPoint x="31.169999999999998" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="BnlXlSoju1qgPTf3SqZH-11" edge="1">
<mxGeometry x="129" y="148" as="geometry">
<Array as="points">
<mxPoint x="508" y="319" />
<mxPoint x="508" y="439" />
</Array>
<mxPoint x="690" y="439" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-21" value="Sends an email to users&lt;br&gt;new (encrypted) key pair" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-15" vertex="1" connectable="0">
<mxGeometry x="0.4583" y="-1" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="BnlXlSoju1qgPTf3SqZH-11" target="BnlXlSoju1qgPTf3SqZH-9" edge="1">
<mxGeometry x="129" y="148" as="geometry">
<Array as="points">
<mxPoint x="508" y="319" />
<mxPoint x="508" y="199" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-22" value="Stores old key with TTL&lt;br&gt;and user&#39;s email address" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-16" vertex="1" connectable="0">
<mxGeometry x="0.3889" relative="1" as="geometry">
<mxPoint x="15.33" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-11" value="Creator" style="outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#D05C17;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.lambda_function;" parent="1" vertex="1">
<mxGeometry x="390" y="280" width="78" height="78" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="BnlXlSoju1qgPTf3SqZH-2" target="BnlXlSoju1qgPTf3SqZH-11" edge="1">
<mxGeometry x="129" y="148" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-19" value="Triggers periodically" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-13" vertex="1" connectable="0">
<mxGeometry x="-0.5182" y="-1" relative="1" as="geometry">
<mxPoint x="36.9" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="BnlXlSoju1qgPTf3SqZH-12" edge="1">
<mxGeometry x="129" y="148" as="geometry">
<Array as="points">
<mxPoint x="936" y="439" />
</Array>
<mxPoint x="768" y="439" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-28" value="Sends an email informing&lt;br&gt;IAM user that existing key&lt;br&gt;has been deleted" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-23" vertex="1" connectable="0">
<mxGeometry x="-0.0399" y="-1" relative="1" as="geometry">
<mxPoint x="-4.17" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="BnlXlSoju1qgPTf3SqZH-12" target="BnlXlSoju1qgPTf3SqZH-10" edge="1">
<mxGeometry x="129" y="148" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-27" value="Delete existing&lt;br&gt;IAM key pair" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-26" vertex="1" connectable="0">
<mxGeometry x="0.2647" relative="1" as="geometry">
<mxPoint x="20.17" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-12" value="Destructor&amp;nbsp;" style="outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#D05C17;strokeColor=none;dashed=0;verticalLabelPosition=middle;verticalAlign=middle;align=left;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.lambda_function;labelPosition=right;" parent="1" vertex="1">
<mxGeometry x="897.33" y="280.5" width="78" height="78" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="BnlXlSoju1qgPTf3SqZH-9" target="BnlXlSoju1qgPTf3SqZH-12" edge="1">
<mxGeometry x="129" y="148" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-25" value="DynamoDB streams are sent&lt;br&gt;to destructor to delete old IAM&lt;br&gt;access key associated with user" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="BnlXlSoju1qgPTf3SqZH-17" vertex="1" connectable="0">
<mxGeometry x="-0.2943" y="1" relative="1" as="geometry">
<mxPoint x="23.67" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-32" value="1" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="290" y="290" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-33" value="2" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="578" y="278" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-34" value="3" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="578" y="398" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-35" value="4" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="575" y="165" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-36" value="5" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="870" y="158" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-37" value="6" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="825" y="285" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="BnlXlSoju1qgPTf3SqZH-38" value="7" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fontFamily=Tahoma;spacingBottom=4;spacingRight=2;strokeColor=#d3d3d3;labelBackgroundColor=none;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="883" y="397" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="lGLhvRVPtBI0HAwZn8tC-1" value="Mailer" style="outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#D05C17;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.lambda_function;" parent="1" vertex="1">
<mxGeometry x="690" y="401" width="78" height="78" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file modified iam-key-rotator.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7f268fb

Please sign in to comment.