-
Notifications
You must be signed in to change notification settings - Fork 1
Secrets verification #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Nareshp1
wants to merge
44
commits into
main
Choose a base branch
from
secrets-verification
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Secrets verification #149
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
b26ed18
fix(secrets): Move changes from old api repo to monorepo branch
Nareshp1 7a17d57
fix(secrets): Simplified error handling for invalid credential payloads
Nareshp1 5663551
fix(tests): Ignore test coverage files
Nareshp1 2467078
feat(tests): Adding initial tests for creds verification
Nareshp1 10d6117
fix(secrets): Added additional handling for invalid provider in secre…
Nareshp1 9218f89
fix(tests): Updated AWS Secrets payload in config to reflect current …
Nareshp1 8517b8c
feat(tests): Added tests for CredsFactory class
Nareshp1 4b2ff5e
fix(schemas): Extra period in error message
Nareshp1 f5311d9
fix(tests): Update credential payload to use empty dictionary when te…
Nareshp1 e6bf1fc
fix(tests): fix api route for fixture test (in-progress)
Nareshp1 b8c3911
feat(tests): add test coverage for AWS secrets schema
Nareshp1 fcd20a2
fix(tests): Update pyproject.toml to ignore botocore deprecated warni…
Nareshp1 0ae48eb
fix(api): Update user error message for updating secrets endpoint.
Nareshp1 0b22652
fix(crud): Remove unnecessary commit line from crud function.
Nareshp1 83e76f8
fix(tests): Working full coverage unit api tests for users secrets en…
Nareshp1 b672026
feat(tests): working full unit test coverage for crud secrets.
Nareshp1 67c999f
feat(tests): full test coverage for creds verification on AWS.
Nareshp1 9603e5a
feat(frontend): Combined secrets pages into a single section with tab…
Nareshp1 61330c2
feat(frontend): Working creds verification endpoint from frontend.
Nareshp1 64dd799
feat(frontend): Updated function logic for creating the payload used …
Nareshp1 121c388
feat(cli): Updated secrets verification endpoint for cli
Nareshp1 cf3b147
fix(workflows): Fix ruff errors.
Nareshp1 d8ed96d
fix(api): add init for api cloud module
alexchristy c598a96
feat(tests): add integration tests for aws creds verification class
alexchristy ed0262b
fix(tests): fix adding credentials in deploy tests to match new secre…
alexchristy fd12763
Merge branch 'main' into secrets-verification
Nareshp1 9076142
fix(tests): Fix failing ruff tests
Nareshp1 332c895
fix(tests): Fix MyPy error with crud_secrets test.
Nareshp1 8982a19
fix(tests): More ruff error fixes :(
Nareshp1 3b15018
fix(tests): More ruff fixes :(
Nareshp1 4d7b3df
fix(tests): Fix ruff checks
Nareshp1 6109ada
Fix(secrets verification): Fix typos.
Nareshp1 be0a584
fix(tests): Updated test config for aws secrets and renamed aws tests…
Nareshp1 168f099
fix(secrets verification): Update secrets functionality to use discri…
Nareshp1 0d3dc84
fix(secrets verification): Update endpoint to use newly created secre…
Nareshp1 9c68d2a
fix(secrets verification): Update provider enum for discriminated uni…
Nareshp1 08a52cf
fix(tests): Update secrets tests to use new discriminated union logic.
Nareshp1 ac16d37
fix(tests): Fix usage of old CredsVerify Schema to use new discrimina…
Nareshp1 8c9136f
fix(secrets verification): Ruff fixes.
Nareshp1 22551dd
fix:(cli): Updated cli to use updated credential payload.
Nareshp1 89a90d9
fix(frontend): Updated endpoint calls to use new credential payload.
Nareshp1 6872182
fix(schemas): Updated error message for aws secrets validators.
Nareshp1 d6adab5
feat(frontend): Added additional parsing for pydantic validation erro…
Nareshp1 cc8d069
spacing fix.
Nareshp1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,3 +13,5 @@ testing-out/ | |
| # Misc | ||
| .vscode/ | ||
|
|
||
| # Tests | ||
| .coverage | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Cloud controls for the OpenLabs API.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| import logging | ||
| from datetime import UTC, datetime | ||
| from typing import List, Tuple | ||
|
|
||
| import boto3 | ||
| from botocore.exceptions import ClientError | ||
|
|
||
| from src.app.schemas.message_schema import MessageSchema | ||
| from src.app.schemas.secret_schema import AWSSecrets, SecretSchema | ||
|
|
||
| from .base_creds import AbstractBaseCreds | ||
|
|
||
| # Configure logging | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class AWSCreds(AbstractBaseCreds): | ||
| """Credential verification for AWS.""" | ||
|
|
||
| credentials: AWSSecrets | ||
|
|
||
| def __init__(self, credentials: AWSSecrets) -> None: | ||
| """Initialize AWS credentials verification object.""" | ||
| self.credentials = credentials | ||
|
|
||
| def get_user_creds(self) -> dict[str, str]: | ||
| """Convert user AWS secrets to dictionary for encryption.""" | ||
| return { | ||
| "aws_access_key": self.credentials.aws_access_key, | ||
| "aws_secret_key": self.credentials.aws_secret_key, | ||
| } | ||
|
|
||
| def update_secret_schema( | ||
| self, secrets: SecretSchema, encrypted_data: dict[str, str] | ||
| ) -> SecretSchema: | ||
| """Update user secrets schema with newly encrypted secrets.""" | ||
| secrets.aws_access_key = encrypted_data["aws_access_key"] | ||
| secrets.aws_secret_key = encrypted_data["aws_secret_key"] | ||
| secrets.aws_created_at = datetime.now(UTC) | ||
| return secrets | ||
|
|
||
| def verify_creds(self) -> Tuple[bool, MessageSchema]: | ||
| """Verify credentials authenticate to an AWS account.""" | ||
| try: | ||
| # --- Step 1: Basic Authentication with STS --- | ||
| # Created shared session for authentication and IAM permission check | ||
| session = boto3.Session( | ||
| aws_access_key_id=self.credentials.aws_access_key, | ||
| aws_secret_access_key=self.credentials.aws_secret_key, | ||
| ) | ||
| client = session.client("sts") | ||
| caller_identity = ( | ||
| client.get_caller_identity() | ||
| ) # will raise an error if not valid | ||
| caller_arn = caller_identity["Arn"] | ||
| logger.info( | ||
| "AWS credentials successfully authenticated for ARN: %s", caller_arn | ||
| ) | ||
|
|
||
| if caller_arn.endswith( | ||
| ":root" | ||
| ): # If root access key credentials are used, skip permissions check as root user has all permissions | ||
| return ( | ||
| True, | ||
| MessageSchema( | ||
| message="AWS credentials authenticated and all required permissions are present." | ||
| ), | ||
| ) | ||
|
|
||
| # --- Step 2: Simulate permissions for a sample of minimum critical actions --- | ||
| iam_client = session.client("iam") | ||
|
|
||
| actions_to_test = [ | ||
| # For Instance | ||
| "ec2:RunInstances", | ||
| "ec2:TerminateInstances", | ||
| "ec2:DescribeInstances", | ||
| # For Vpc | ||
| "ec2:CreateVpc", | ||
| "ec2:DeleteVpc", | ||
| "ec2:DescribeVpcs", | ||
| # For Subnet | ||
| "ec2:CreateSubnet", | ||
| "ec2:DeleteSubnet", | ||
| "ec2:DescribeSubnets", | ||
| # For InternetGateway | ||
| "ec2:CreateInternetGateway", | ||
| "ec2:DeleteInternetGateway", | ||
| "ec2:AttachInternetGateway", | ||
| "ec2:DetachInternetGateway", | ||
| # For Eip and NatGateway | ||
| "ec2:AllocateAddress", # Create EIP | ||
| "ec2:ReleaseAddress", # Delete EIP | ||
| "ec2:AssociateAddress", | ||
| "ec2:CreateNatGateway", | ||
| "ec2:DeleteNatGateway", | ||
| # For KeyPair | ||
| "ec2:CreateKeyPair", | ||
| "ec2:DeleteKeyPair", | ||
| # For SecurityGroup and SecurityGroupRule | ||
| "ec2:CreateSecurityGroup", | ||
| "ec2:DeleteSecurityGroup", | ||
| "ec2:AuthorizeSecurityGroupIngress", | ||
| "ec2:RevokeSecurityGroupIngress", | ||
| "ec2:AuthorizeSecurityGroupEgress", | ||
| "ec2:RevokeSecurityGroupEgress", | ||
| # For RouteTable, Route, and RouteTableAssociation | ||
| "ec2:CreateRouteTable", | ||
| "ec2:DeleteRouteTable", | ||
| "ec2:CreateRoute", | ||
| "ec2:DeleteRoute", | ||
| "ec2:AssociateRouteTable", | ||
| "ec2:DisassociateRouteTable", | ||
| # For Transit Gateway --- | ||
| "ec2:CreateTransitGateway", | ||
| "ec2:DeleteTransitGateway", | ||
| "ec2:CreateTransitGatewayVpcAttachment", | ||
| "ec2:DeleteTransitGatewayVpcAttachment", | ||
| "ec2:CreateTransitGatewayRoute", | ||
| "ec2:DeleteTransitGatewayRoute", | ||
| "ec2:DescribeTransitGateways", | ||
| "ec2:DescribeTransitGatewayVpcAttachments", | ||
| ] | ||
|
|
||
| simulation_results = iam_client.simulate_principal_policy( | ||
| PolicySourceArn=caller_arn, ActionNames=actions_to_test | ||
| ) | ||
|
|
||
| # --- Step 3: Evaluate the simulation results --- | ||
| denied_actions: List[str] = [] | ||
| for result in simulation_results["EvaluationResults"]: | ||
| if result["EvalDecision"] != "allowed": | ||
| denied_actions.append(result["EvalActionName"]) | ||
|
|
||
| if denied_actions: | ||
| error_message = f"Authentication succeeded, but the user/group is missing required permissions. The following actions were denied: {', '.join(denied_actions)}" | ||
| logger.error(error_message) | ||
| return ( | ||
| False, | ||
| MessageSchema( | ||
| message=f"Insufficient permissions for your AWS account user/group. Please ensure the following permissions are added: {', '.join(denied_actions)}" | ||
| ), | ||
| ) | ||
| logger.info("All simulated actions were allowed for ARN: %s", caller_arn) | ||
| return ( | ||
| True, | ||
| MessageSchema( | ||
| message="AWS credentials authenticated and all required permissions are present." | ||
| ), | ||
| ) | ||
| except ClientError as e: | ||
| error_code = e.response["Error"]["Code"] | ||
| if error_code in ("InvalidClientTokenId", "SignatureDoesNotMatch"): | ||
| message = "AWS credentials could not be authenticated. Please ensure you are providing credentials that are linked to a valid AWS account." | ||
| elif error_code == "AccessDenied": | ||
| message = "AWS credentials are valid, but lack permissions to perform the permissions verification. Please ensure you give your AWS account user/group has the iam:SimulatePrincipalPolicy permission attached to a policy." | ||
| else: | ||
| message = e.response["Error"]["Message"] | ||
| logger.error("AWS verification failed: %s", message) | ||
| return ( | ||
| False, | ||
| MessageSchema(message=message), | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.