|
| 1 | +--- |
| 2 | +title: Kosli Capture - Security |
| 3 | +sidebarTitle: Security |
| 4 | +description: "Learn about the security of Kosli Capture" |
| 5 | +tag: "BETA" |
| 6 | +--- |
| 7 | + |
| 8 | +<Warning> |
| 9 | +Kosli Capture is still in active development. Its capabilities and configuration format may change, and onboarding is done together with Kosli's Customer Success team. |
| 10 | +</Warning> |
| 11 | + |
| 12 | +## Kosli Capture permissions |
| 13 | + |
| 14 | +The Kosli Capture managed service uses the public AWS APIs to extract information about your cloud environments. In order to do this, you need to provide Kosli with an IAM role that allows access to these APIs. The role is created and owned by you. Kosli publishes a CloudFormation template, for use in AWS, showing the permissions needed. The template is publicly accessible and can be used directly within an `aws cloudformation create-stack` call. |
| 15 | + |
| 16 | +The CloudFormation template we share with you includes a "phone-home" feature that notifies Kosli when a CloudFormation stack has been built from it; this allows us to pick up the AWS AccountId for the account in which you have used the CloudFormation template without you needing to do anything. This automation is especially useful when you deploy the template as a StackSet within an Organizational Unit. |
| 17 | + |
| 18 | +### Assume role |
| 19 | + |
| 20 | +The IAM role defined within the CloudFormation template includes an "assume role" policy granting permission from Kosli. This appears as: |
| 21 | + |
| 22 | +```yaml |
| 23 | + KosliCaptureAccessRole: |
| 24 | + Type: AWS::IAM::Role |
| 25 | + Properties: |
| 26 | + RoleName: !Ref RoleName |
| 27 | + Description: >- |
| 28 | + Read-only access for Kosli Capture SDLC compliance evidence collection. |
| 29 | + Managed by CloudFormation; do not edit in place. |
| 30 | + MaxSessionDuration: 3600 |
| 31 | + AssumeRolePolicyDocument: |
| 32 | + Version: "2012-10-17" |
| 33 | + Statement: |
| 34 | + - Sid: AllowKosliToAssumeWithExternalId |
| 35 | + Effect: Allow |
| 36 | + Principal: |
| 37 | + AWS: !Ref TrustedPrincipalArn |
| 38 | + Action: sts:AssumeRole |
| 39 | + Condition: |
| 40 | + StringEquals: |
| 41 | + sts:ExternalId: !Ref ExternalId |
| 42 | +``` |
| 43 | +
|
| 44 | +### All permissions needed |
| 45 | +
|
| 46 | +The IAM role defined within the Cloudformation template includes a number of IAM policy statements, granting read-only access to some AWS APIs. The statements are: |
| 47 | +
|
| 48 | +```yaml |
| 49 | +Statement: |
| 50 | + |
| 51 | + # How Capture finds what to snapshot. Discovery lists the ECS |
| 52 | + # clusters in the account and reads each cluster's tags from the |
| 53 | + # same DescribeClusters call. |
| 54 | + # |
| 55 | + # Worth knowing for a security review: these are inventory calls |
| 56 | + # and none of them returns application data. DescribeTaskDefinition |
| 57 | + # is the widest - a task definition holds the container image, the |
| 58 | + # command, and any environment variables written into the |
| 59 | + # definition itself in plain text. Values injected from Secrets |
| 60 | + # Manager or Parameter Store are named there rather than resolved, |
| 61 | + # so what comes back is the reference and not the secret. |
| 62 | + - Sid: EcsInventory |
| 63 | + Effect: Allow |
| 64 | + Action: |
| 65 | + - ecs:DescribeCapacityProviders |
| 66 | + - ecs:DescribeClusters |
| 67 | + - ecs:DescribeContainerInstances |
| 68 | + - ecs:DescribeServices |
| 69 | + - ecs:DescribeTaskDefinition |
| 70 | + - ecs:DescribeTasks |
| 71 | + - ecs:ListClusters |
| 72 | + - ecs:ListContainerInstances |
| 73 | + - ecs:ListServices |
| 74 | + - ecs:ListTagsForResource |
| 75 | + - ecs:ListTaskDefinitionFamilies |
| 76 | + - ecs:ListTaskDefinitions |
| 77 | + - ecs:ListTasks |
| 78 | + Resource: "*" |
| 79 | + |
| 80 | + - Sid: LambdaInventory |
| 81 | + Effect: Allow |
| 82 | + Action: |
| 83 | + - lambda:GetFunctionConfiguration |
| 84 | + - lambda:GetPolicy |
| 85 | + - lambda:ListAliases |
| 86 | + - lambda:ListFunctions |
| 87 | + - lambda:ListTags |
| 88 | + - lambda:ListVersionsByFunction |
| 89 | + Resource: "*" |
| 90 | + |
| 91 | + # lambda:GetFunction returns a pre-signed URL to the deployment |
| 92 | + # package. That is source-code access, so it is denied outright. |
| 93 | + - Sid: NeverDownloadFunctionCode |
| 94 | + Effect: Deny |
| 95 | + Action: |
| 96 | + - lambda:GetFunction |
| 97 | + - lambda:GetLayerVersion |
| 98 | + Resource: "*" |
| 99 | +``` |
| 100 | +
|
| 101 | +## How Kosli isolates customers |
| 102 | +
|
| 103 | +Kosli Capture runs as a shared, autoscaled service, but each job runs under a role that is scoped to |
| 104 | +one customer: |
| 105 | +
|
| 106 | +* A Kosli Capture worker picks up a job for your organization and assumes a Kosli-side role that |
| 107 | + exists only for your organization. Only that role is permitted to call AssumeRole into your |
| 108 | + account with your ExternalId. A Kosli Capture worker running for a different customer is unable |
| 109 | + to connect to your cloud account. |
| 110 | +* When the job finishes, those credentials are discarded. A worker holding credentials for your |
| 111 | + cloud account has no path to anyone else's account. |
| 112 | +* The ExternalId lives in Parameter Store and is readable only by the Kosli-side role for your |
| 113 | + organization. The shared task role cannot read any customer's ExternalId. Separation is enforced |
| 114 | + by IAM, not by application code. |
| 115 | +
|
| 116 | +The trust policy on the role in your account limits access to the AWS account in which Kosli |
| 117 | +Capture is running. The ExternalId acts as a shared secret between Kosli and you, so that only |
| 118 | +Kosli Capture is permitted to assume the role. |
| 119 | +
|
| 120 | +Kosli Capture itself does not hold any customer data. Snapshots taken by Kosli Capture are |
| 121 | +immediately sent to Kosli through the same ingest path as your existing pipelines. |
0 commit comments