diff --git a/aws/lib/regional-stack.ts b/aws/lib/regional-stack.ts index 8fba9227..914a7ec2 100644 --- a/aws/lib/regional-stack.ts +++ b/aws/lib/regional-stack.ts @@ -87,8 +87,8 @@ export class RegionalStack extends Stack { const integrationTemplateUpload = new s3deploy.BucketDeployment(this, 'UploadIntegrationTemplate', { sources: [ s3deploy.Source.data( - 'integration-v2.cfn.yaml', - fs.readFileSync(path.join(__dirname, '../../frontend/public/integration-v2.cfn.yaml'), 'utf8'), + 'integration-v3.cfn.yaml', + fs.readFileSync(path.join(__dirname, '../../frontend/public/integration-v3.cfn.yaml'), 'utf8'), ), ], destinationBucket: publicS3Bucket, diff --git a/backend/api/aws_integration.go b/backend/api/aws_integration.go index 80e7d710..0341c284 100644 --- a/backend/api/aws_integration.go +++ b/backend/api/aws_integration.go @@ -15,6 +15,7 @@ func AWSIntegrationFromModel(integration *model.AWSIntegration) apispec.AWSInteg CreationTime: integration.CreationTime, TeamId: integration.TeamId.String(), Name: integration.Name, + RoleArn: integration.RoleARN, GetAccountNamesFromOrganizations: integration.GetAccountNamesFromOrganizations, ManageScps: integration.ManageSCPs, } diff --git a/frontend/public/integration-v2.cfn.yaml b/frontend/public/integration-v3.cfn.yaml similarity index 72% rename from frontend/public/integration-v2.cfn.yaml rename to frontend/public/integration-v3.cfn.yaml index 428d5d76..77071b1e 100644 --- a/frontend/public/integration-v2.cfn.yaml +++ b/frontend/public/integration-v3.cfn.yaml @@ -44,7 +44,7 @@ # Typically we would use the AWS CDK instead of writing CloudFormation templates directly, but CDK # output is much less readable, and we feel it's important that you can review the templates you're # deploying with ease. -Description: Cloud Snitch AWS Integration (V1) +Description: Cloud Snitch AWS Integration (V3) # # These are the input parameters you'll need to provide us. Parameters: @@ -61,6 +61,13 @@ Parameters: - 'Yes' - 'No' Description: Whether to allow read access to AWS Organizations data such as account names. + AllowSCPManagement: + Type: String + Default: 'No' + AllowedValues: + - 'Yes' + - 'No' + Description: Whether to allow the creation of additional service control policies for accounts. S3BucketName: Type: String Default: '' @@ -75,6 +82,7 @@ Parameters: Conditions: HasOrganizationsAccess: !Equals [!Ref AllowOrganizationsAccess, 'Yes'] HasS3BucketName: !Not [!Equals [!Ref S3BucketName, '']] + HasSCPManagement: !Equals [!Ref AllowSCPManagement, 'Yes'] # # Now for the resources... Resources: @@ -116,6 +124,67 @@ Resources: PolicyName: organizations Roles: - !Ref IntegrationRole + # If you specify that you want to allow Cloud Snitch to manage service control policies, we + # create a policy and attach it to the role. + IntegrationSCMManagementPolicy: + Condition: HasSCPManagement + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + # These actions allow us to get general information about the organization. + - Action: + - organizations:ListAccounts + - organizations:ListParents + - organizations:ListRoots + - iam:GenerateOrganizationsAccessReport + - iam:GetOrganizationsAccessReport + Effect: Allow + Resource: '*' + # Allow enumerating and attaching service control policies to accounts. Note + # that attaching and detaching policies also requires permissions on the policy + # resource, which are granted in the next statement. + - Action: + - organizations:AttachPolicy + - organizations:DetachPolicy + - organizations:ListPoliciesForTarget + Effect: Allow + Resource: !Sub 'arn:aws:organizations::${AWS::AccountId}:account/*' + Condition: + StringEquals: + organizations:PolicyType: SERVICE_CONTROL_POLICY + # Allow operating on service control policies that are tagged as being managed + # by Cloud Snitch. Permission is not granted to operate on any other policies. + - Action: + - organizations:AttachPolicy + - organizations:DetachPolicy + - organizations:CreatePolicy + - organizations:DescribePolicy + - organizations:DeletePolicy + - organizations:UpdatePolicy + Effect: Allow + Resource: '*' + Condition: + StringEquals: + aws:ResourceTag/CloudSnitchManaged: 'true' + organizations:PolicyType: SERVICE_CONTROL_POLICY + # Lastly, we need to be able to assign the Cloud Snitch managed tag to policies, + # but only on creation. We cannot add the tag to existing policies. + - Action: organizations:TagResource + Effect: Allow + Resource: !Sub 'arn:aws:organizations::${AWS::AccountId}:policy/*' + Condition: + # There's an important subtlety at play here: When the policy is created, + # aws:ResourceTag is based on the tags in the request. Otherwise, the + # aws:ResourceTag is based on the tags already on the resource. This + # allows us to have full control over our policies without being able to + # touch existing policies. + StringEquals: + aws:ResourceTag/CloudSnitchManaged: 'true' + Version: '2012-10-17' + PolicyName: scp-management + Roles: + - !Ref IntegrationRole # If you specify an S3 bucket name, we create a policy for read access and attach it to the role. IntegrationS3Policy: Condition: HasS3BucketName diff --git a/frontend/src/app/(public-area)/cookie-policy/page.tsx b/frontend/src/app/(public-area)/cookie-policy/page.tsx index 9ce0f68e..66d2277f 100644 --- a/frontend/src/app/(public-area)/cookie-policy/page.tsx +++ b/frontend/src/app/(public-area)/cookie-policy/page.tsx @@ -14,7 +14,7 @@ const Page = () => {
diff --git a/frontend/src/app/(public-area)/pricing/page.tsx b/frontend/src/app/(public-area)/pricing/page.tsx index 3eef6e71..b6a76c97 100644 --- a/frontend/src/app/(public-area)/pricing/page.tsx +++ b/frontend/src/app/(public-area)/pricing/page.tsx @@ -80,13 +80,12 @@ const Page = () => { credits.
- Example: You sign up at the begining of - the month and create your one-person team using an Individual plan. You then set up an AWS - integration and begin ingesting CloudTrail data for 3 AWS accounts. This results in a charge of 3 x - $0.99 = $2.97. Halfway through the month, you upgrade to the Team plan, resulting in a charge of 3 x - ($9.99 - $0.99) x 50% = $13.50. You also decide to add another account, which results in an - additional $9.99 x 50% = $4.98 charge. At the beginning of future billing cycles, you simply pay 4 x - $9.99 = $39.96. + Example: You sign up at the begining of the month and + create your one-person team using an Individual plan. You then set up an AWS integration and begin + ingesting CloudTrail data for 3 AWS accounts. This results in a charge of 3 x $0.99 = $2.97. Halfway + through the month, you upgrade to the Team plan, resulting in a charge of 3 x ($9.99 - $0.99) x 50% + = $13.50. You also decide to add another account, which results in an additional $9.99 x 50% = $4.98 + charge. At the beginning of future billing cycles, you simply pay 4 x $9.99 = $39.96.
*This example excludes any applicable taxes.
diff --git a/frontend/src/app/(public-area)/terms-of-service/page.tsx b/frontend/src/app/(public-area)/terms-of-service/page.tsx index 2016fe95..86c40fd3 100644 --- a/frontend/src/app/(public-area)/terms-of-service/page.tsx +++ b/frontend/src/app/(public-area)/terms-of-service/page.tsx @@ -14,7 +14,7 @@ const Page = () => {
diff --git a/frontend/src/app/(user-area)/teams/[teamId]/Header.tsx b/frontend/src/app/(user-area)/teams/[teamId]/Header.tsx index 8882c0d5..d6ef5570 100644 --- a/frontend/src/app/(user-area)/teams/[teamId]/Header.tsx +++ b/frontend/src/app/(user-area)/teams/[teamId]/Header.tsx @@ -55,9 +55,7 @@ export const Header = (props: Props) => { )} {memberships && memberships.length > 1 && (
There's nothing here, but we can fix that!
{needsSubscriptionSetup && ( <> -- Activate a subscription -
+Activate a subscription
Head over to your team's{' '} @@ -354,9 +352,7 @@ const Page = () => { )} {needsAwsIntegrationSetup && ( <> -
- Integrate with your AWS account -
+Integrate with your AWS account
Go to your team's{' '} diff --git a/frontend/src/app/(user-area)/teams/[teamId]/settings/billing/page.tsx b/frontend/src/app/(user-area)/teams/[teamId]/settings/billing/page.tsx index cc8c2bf3..eb50ba9c 100644 --- a/frontend/src/app/(user-area)/teams/[teamId]/settings/billing/page.tsx +++ b/frontend/src/app/(user-area)/teams/[teamId]/settings/billing/page.tsx @@ -373,7 +373,7 @@ const Page = () => {