├── test ├── trigger-events │ ├── outputs.tf │ ├── variables.tf │ ├── versions.tf │ ├── main.tf │ └── README.md ├── fixtures │ ├── organizational │ │ ├── outputs.tf │ │ ├── backend.tf │ │ ├── variables.tf │ │ └── main.tf │ ├── single-account-k8s │ │ ├── outputs.tf │ │ ├── backend.tf │ │ ├── variables.tf │ │ └── main.tf │ ├── single-account-apprunner │ │ ├── outputs.tf │ │ ├── backend.tf │ │ ├── variables.tf │ │ └── main.tf │ ├── organizational-k8s │ │ ├── backend.tf │ │ ├── variables.tf │ │ └── main.tf │ └── single-account-ecs │ │ ├── variables.tf │ │ └── main.tf └── eks │ ├── data.tf │ ├── versions.tf │ ├── README.md │ ├── outputs.tf │ ├── variables.tf │ └── main.tf ├── examples ├── organizational │ ├── outputs.tf │ ├── data.tf │ ├── diagram-org.png │ ├── versions.tf │ ├── ecs.tf │ ├── cloudtrail.tf │ ├── diagram-permissions.py │ ├── permissions.tf │ └── main.tf ├── single-account-k8s │ ├── outputs.tf │ ├── data.tf │ ├── diagram.png │ ├── versions.tf │ ├── main.tf │ ├── cloudtrail.tf │ ├── credentials.tf │ ├── variables.tf │ ├── cloud-connector.tf │ └── diagram.py ├── single-account ├── single-account-ecs │ ├── data.tf │ ├── diagram-single.png │ ├── outputs.tf │ ├── versions.tf │ ├── ecs.tf │ ├── cloudtrail.tf │ ├── main.tf │ └── diagram-single.py └── single-account-apprunner │ ├── data.tf │ ├── diagram-single.png │ ├── outputs.tf │ ├── versions.tf │ ├── cloudtrail.tf │ ├── main.tf │ ├── variables.tf │ └── diagram-single.py ├── CODEOWNERS ├── modules ├── infrastructure │ ├── resource-group │ │ ├── outputs.tf │ │ ├── versions.tf │ │ ├── main.tf │ │ ├── variables.tf │ │ └── README.md │ ├── permissions │ │ ├── general │ │ │ ├── outputs.tf │ │ │ ├── data.tf │ │ │ ├── versions.tf │ │ │ ├── main.tf │ │ │ ├── variables.tf │ │ │ └── README.md │ │ ├── cloud-connector │ │ │ ├── outputs.tf │ │ │ ├── data.tf │ │ │ ├── versions.tf │ │ │ ├── variables.tf │ │ │ ├── main.tf │ │ │ └── README.md │ │ ├── cloud-scanning │ │ │ ├── outputs.tf │ │ │ ├── data.tf │ │ │ ├── versions.tf │ │ │ ├── variables.tf │ │ │ ├── main.tf │ │ │ └── README.md │ │ ├── iam-user │ │ │ ├── versions.tf │ │ │ ├── outputs.tf │ │ │ ├── variables.tf │ │ │ └── main.tf │ │ ├── org-role-eks │ │ │ ├── versions.tf │ │ │ ├── outputs.tf │ │ │ ├── variables.tf │ │ │ ├── main.tf │ │ │ └── README.md │ │ └── org-role-ecs │ │ │ ├── versions.tf │ │ │ ├── outputs.tf │ │ │ ├── variables.tf │ │ │ └── main.tf │ ├── cloudtrail │ │ ├── data.tf │ │ ├── versions.tf │ │ ├── sns.tf │ │ ├── outputs.tf │ │ ├── main.tf │ │ ├── sns_permissions.tf │ │ ├── variables.tf │ │ ├── s3.tf │ │ └── kms.tf │ ├── ecs-vpc │ │ ├── versions.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── vpc.tf │ │ ├── variables.tf │ │ └── README.md │ ├── ssm │ │ ├── versions.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── README.md │ ├── codebuild │ │ ├── versions.tf │ │ ├── cloudwatch.tf │ │ ├── outputs.tf │ │ ├── main.tf │ │ ├── variables.tf │ │ ├── codebuild-security.tf │ │ └── README.md │ ├── cloudtrail_s3-sns-sqs │ │ ├── versions.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── main.tf │ └── sqs-sns-subscription │ │ ├── versions.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ ├── main.tf │ │ └── README.md └── services │ ├── cloud-connector-ecs │ ├── outputs.tf │ ├── main.tf │ ├── data.tf │ ├── versions.tf │ ├── cloudwatch.tf │ ├── sqs.tf │ ├── locals.tf │ ├── sec-group.tf │ ├── cloudconnector-config.tf │ ├── ecs-service.tf │ └── ecs-service-autoscaling.tf │ └── cloud-connector-apprunner │ ├── outputs.tf │ ├── data.tf │ ├── sqs.tf │ ├── versions.tf │ ├── main.tf │ ├── cloudwatch.tf │ ├── cloudconnector-config.tf │ ├── variables.tf │ └── apprunner.tf ├── examples-internal └── organizational-k8s-threat-reuse_cloudtrail_s3 │ ├── outputs.tf │ ├── data.tf │ ├── diagram.png │ ├── versions.tf │ ├── main.tf │ ├── cloud-connector.tf │ ├── variables.tf │ └── diagram.py ├── resources ├── apprunner-icon.png ├── diag-sysdig-icon.png ├── diag-registry-icon.png ├── scripts │ ├── generate_providers.sh │ ├── terraform-clean.sh │ └── terraform_validate.sh └── sfc-policy.json ├── use-cases ├── resources │ ├── vuln-scanner.png │ ├── org-three-way-with-sns.png │ ├── org-three-with-s3-forward.png │ ├── org-three-with-s3-forward.py │ └── org-three-way-with-sns.py ├── single-existing-cloudtrail.md └── org-single-account.md ├── Gemfile ├── .github ├── git-chlog │ ├── CHANGELOG.tpl.md │ └── config.yaml ├── workflows │ ├── issues-slack-notify.yml │ ├── release.yaml │ └── ci-test-cleanup.yaml └── PULL_REQUEST_TEMPLATE.md ├── .kitchen.yml ├── .gitignore ├── Makefile ├── DecisionRecord.md └── .pre-commit-config.yaml /test/trigger-events/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/trigger-events/variables.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/organizational/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/single-account-k8s/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sysdiglabs/cloud-native 2 | -------------------------------------------------------------------------------- /examples/single-account: -------------------------------------------------------------------------------- 1 | single-account-ecs -------------------------------------------------------------------------------- /test/fixtures/organizational/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/single-account-k8s/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/infrastructure/resource-group/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/single-account-apprunner/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-connector/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/outputs.tf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_caller_identity" "me" {} 2 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_region" "current" {} 2 | -------------------------------------------------------------------------------- /examples/single-account-ecs/data.tf: -------------------------------------------------------------------------------- 1 | data "sysdig_secure_connection" "current" {} 2 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/data.tf: -------------------------------------------------------------------------------- 1 | data "sysdig_secure_connection" "current" {} 2 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/data.tf: -------------------------------------------------------------------------------- 1 | data "sysdig_secure_connection" "current" {} 2 | -------------------------------------------------------------------------------- /test/eks/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_eks_cluster_auth" "eks_auth" { 2 | name = var.name 3 | } 4 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/data.tf: -------------------------------------------------------------------------------- 1 | data "sysdig_secure_connection" "current" {} 2 | -------------------------------------------------------------------------------- /examples/organizational/data.tf: -------------------------------------------------------------------------------- 1 | data "sysdig_secure_connection" "current" {} 2 | data "aws_caller_identity" "me" {} 3 | -------------------------------------------------------------------------------- /examples/single-account-k8s/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_region" "current" {} 2 | data "sysdig_secure_connection" "current" {} 3 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_iam_user" "this" { 2 | user_name = var.sfc_user_name 3 | } 4 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-connector/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_iam_user" "this" { 2 | user_name = var.sfc_user_name 3 | } 4 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_iam_user" "this" { 2 | user_name = var.sfc_user_name 3 | } 4 | -------------------------------------------------------------------------------- /resources/apprunner-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/resources/apprunner-icon.png -------------------------------------------------------------------------------- /resources/diag-sysdig-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/resources/diag-sysdig-icon.png -------------------------------------------------------------------------------- /resources/diag-registry-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/resources/diag-registry-icon.png -------------------------------------------------------------------------------- /use-cases/resources/vuln-scanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/use-cases/resources/vuln-scanner.png -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/data.tf: -------------------------------------------------------------------------------- 1 | data "aws_region" "current" {} 2 | data "sysdig_secure_connection" "current" {} 3 | -------------------------------------------------------------------------------- /examples/organizational/diagram-org.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/examples/organizational/diagram-org.png -------------------------------------------------------------------------------- /examples/single-account-k8s/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/examples/single-account-k8s/diagram.png -------------------------------------------------------------------------------- /examples/single-account-ecs/diagram-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/examples/single-account-ecs/diagram-single.png -------------------------------------------------------------------------------- /test/eks/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /use-cases/resources/org-three-way-with-sns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/use-cases/resources/org-three-way-with-sns.png -------------------------------------------------------------------------------- /use-cases/resources/org-three-with-s3-forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/use-cases/resources/org-three-with-s3-forward.png -------------------------------------------------------------------------------- /examples/single-account-apprunner/diagram-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/examples/single-account-apprunner/diagram-single.png -------------------------------------------------------------------------------- /test/trigger-events/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/ssm/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org/" 2 | 3 | gem "kitchen-terraform", "~> 6.1.0" 4 | #gem 'aws-sdk', '~> 3.0.1' 5 | #gem 'awspec', '~> 1.24.0' 6 | #gem 'kitchen-verifier-awspec', '~> 0.2.0' 7 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/resource-group/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail_s3-sns-sqs/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/iam-user/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/sqs-sns-subscription/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-connector/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-eks/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysdiglabs/terraform-aws-secure-for-cloud/HEAD/examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/diagram.png -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/cloudwatch.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cloudwatch_log_group" "log" { 2 | name = var.name 3 | retention_in_days = var.cloudwatch_log_retention 4 | tags = var.tags 5 | } 6 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ecs_cluster" "ecs_cluster" { 2 | name = var.name 3 | tags = var.tags 4 | # setting { 5 | # name = "containerInsights" 6 | # value = "enabled" 7 | # } 8 | } 9 | -------------------------------------------------------------------------------- /modules/infrastructure/ssm/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_parameter" "secure_api_token" { 2 | name = "${var.name}-sysdig-secure-api-token" 3 | type = "SecureString" 4 | value = var.sysdig_secure_api_token 5 | tags = var.tags 6 | } 7 | -------------------------------------------------------------------------------- /examples/single-account-ecs/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cloudtrail_sns_topic_arn" { 2 | value = length(module.cloudtrail) > 0 ? module.cloudtrail[0].cloudtrail_sns_arn : var.cloudtrail_sns_arn 3 | description = "ARN of cloudtrail_sns topic" 4 | } 5 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cloudtrail_sns_topic_arn" { 2 | value = length(module.cloudtrail) > 0 ? module.cloudtrail[0].cloudtrail_sns_arn : var.cloudtrail_sns_arn 3 | description = "ARN of cloudtrail_sns topic" 4 | } 5 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/sns.tf: -------------------------------------------------------------------------------- 1 | resource "aws_sns_topic" "cloudtrail" { 2 | # AC_AWS_0502 3 | # Why: Encrypt SNS with KMS 4 | #ts:skip=AC_AWS_0502 Don't encrypt as far as SNS can be provided by customer 5 | name = var.name 6 | tags = var.tags 7 | } 8 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-ecs/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | configuration_aliases = [aws.member] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/sqs.tf: -------------------------------------------------------------------------------- 1 | module "cloud_connector_sqs" { 2 | source = "../../infrastructure/sqs-sns-subscription" 3 | name = var.name 4 | cloudtrail_sns_arn = var.cloudtrail_sns_arn 5 | tags = var.tags 6 | } 7 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | } 7 | sysdig = { 8 | source = "sysdiglabs/sysdig" 9 | version = ">= 0.5.33" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | } 7 | sysdig = { 8 | source = "sysdiglabs/sysdig" 9 | version = ">= 0.5.33" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cloudtrail_sns_arn" { 2 | value = aws_sns_topic.cloudtrail.arn 3 | description = "ARN of Cloudtrail SNS topic" 4 | } 5 | 6 | output "s3_bucket_arn" { 7 | value = aws_s3_bucket.cloudtrail.arn 8 | description = "ARN of Cloudtrail SNS topic" 9 | } 10 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/outputs.tf: -------------------------------------------------------------------------------- 1 | output "project_arn" { 2 | description = "Code Build project arn" 3 | value = aws_codebuild_project.build_project.arn 4 | } 5 | 6 | output "project_name" { 7 | description = "Code Build project name" 8 | value = aws_codebuild_project.build_project.name 9 | } 10 | -------------------------------------------------------------------------------- /examples/organizational/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | configuration_aliases = [aws.member] 7 | } 8 | sysdig = { 9 | source = "sysdiglabs/sysdig" 10 | version = ">= 0.5.33" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/single-account-ecs/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3.0" 3 | required_providers { 4 | # tflint-ignore: terraform_unused_required_providers 5 | aws = { 6 | version = ">= 4.0.0" 7 | } 8 | sysdig = { 9 | source = "sysdiglabs/sysdig" 10 | version = ">= 0.5.33" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | # tflint-ignore: terraform_unused_required_providers 5 | aws = { 6 | version = ">= 4.0.0" 7 | } 8 | sysdig = { 9 | source = "sysdiglabs/sysdig" 10 | version = ">= 0.5.33" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /modules/infrastructure/sqs-sns-subscription/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cloudtrail_sns_subscribed_sqs_url" { 2 | value = aws_sqs_queue.this.url 3 | description = "URL of the cloudtrail-sns subscribed sqs" 4 | } 5 | 6 | output "cloudtrail_sns_subscribed_sqs_arn" { 7 | value = aws_sqs_queue.this.arn 8 | description = "ARN of the cloudtrail-sns subscribed sqs" 9 | } 10 | -------------------------------------------------------------------------------- /modules/infrastructure/ssm/outputs.tf: -------------------------------------------------------------------------------- 1 | output "secure_api_token_secret_name" { 2 | value = aws_ssm_parameter.secure_api_token.name 3 | description = "Name of Sysdig Secure API Token secret" 4 | } 5 | 6 | output "secure_api_token_secret_arn" { 7 | value = aws_ssm_parameter.secure_api_token.arn 8 | description = "ARN of Sysdig Secure API Token secret" 9 | } 10 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | verify_ssl = var.verify_ssl == "auto" ? length(regexall("https://.*?\\.sysdig(cloud)?.com/?", data.sysdig_secure_connection.current.secure_url)) == 1 : var.verify_ssl == "true" 3 | deploy_image_scanning = var.deploy_image_scanning_ecs || var.deploy_image_scanning_ecr || var.deploy_beta_image_scanning_ecr 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/organizational/backend.tf: -------------------------------------------------------------------------------- 1 | # Terraform state storage backend 2 | terraform { 3 | backend "s3" { 4 | bucket = "secure-cloud-terraform-tests-org" # org examples deploy in org/s3 bucket 5 | key = "aws-organizational/terraform.tfstate" 6 | dynamodb_table = "secure-cloud-terraform-tests" 7 | region = "eu-west-3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/single-account-k8s/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 4.0.0" 6 | } 7 | sysdig = { 8 | source = "sysdiglabs/sysdig" 9 | version = ">= 0.5.33" 10 | } 11 | helm = { 12 | source = "hashicorp/helm" 13 | version = ">=2.3.0" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/cloudwatch.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cloudwatch_log_group" "log" { 2 | name_prefix = var.name 3 | retention_in_days = var.cloudwatch_log_retention 4 | tags = var.tags 5 | } 6 | 7 | resource "aws_cloudwatch_log_stream" "stream" { 8 | name = "${var.name}-alerts" 9 | log_group_name = aws_cloudwatch_log_group.log.name 10 | } 11 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/cloudwatch.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cloudwatch_log_group" "log" { 2 | name_prefix = var.name 3 | retention_in_days = var.cloudwatch_log_retention 4 | tags = var.tags 5 | } 6 | 7 | resource "aws_cloudwatch_log_stream" "stream" { 8 | name = "${var.name}-alerts" 9 | log_group_name = aws_cloudwatch_log_group.log.name 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/organizational-k8s/backend.tf: -------------------------------------------------------------------------------- 1 | # Terraform state storage backend 2 | terraform { 3 | backend "s3" { 4 | bucket = "secure-cloud-terraform-tests-org" # org examples deploy in qa org/s3 bucket 5 | key = "aws-organizational-k8s-reuse_cloudtrail/terraform.tfstate" 6 | dynamodb_table = "secure-cloud-terraform-tests" 7 | region = "eu-west-3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-ecs/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sysdig_secure_for_cloud_role_arn" { 2 | value = aws_iam_role.secure_for_cloud_role.arn 3 | description = "organizational secure-for-cloud role arn" 4 | } 5 | 6 | output "sysdig_secure_for_cloud_role_name" { 7 | value = aws_iam_role.secure_for_cloud_role.name 8 | description = "organizational secure-for-cloud role name" 9 | } 10 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sysdig_secure_for_cloud_role_arn" { 2 | value = aws_iam_role.secure_for_cloud_role.arn 3 | description = "organizational secure-for-cloud role arn" 4 | } 5 | 6 | output "sysdig_secure_for_cloud_role_name" { 7 | value = aws_iam_role.secure_for_cloud_role.name 8 | description = "organizational secure-for-cloud role name" 9 | } 10 | -------------------------------------------------------------------------------- /test/eks/README.md: -------------------------------------------------------------------------------- 1 | ## usage 2 | 3 | ```terraform 4 | module "eks"{ 5 | source = "sysdiglabs/secure-for-cloud/aws//test/eks" 6 | default_vpc_subnets = ["", ""] 7 | name = "" 8 | } 9 | 10 | ``` 11 | 12 | - connect to eks 13 | ``` 14 | aws eks --region update-kubeconfig --name 15 | ``` 16 | 17 | - kubectx; select the cluster and enjoy 18 | -------------------------------------------------------------------------------- /test/fixtures/single-account-k8s/backend.tf: -------------------------------------------------------------------------------- 1 | # Terraform state storage backend 2 | terraform { 3 | backend "s3" { 4 | bucket = "secure-cloud-terraform-tests" # single examples deploy in qa org/cloudnative account/s3 bucket 5 | key = "aws-single-account-k8s/terraform.tfstate" 6 | dynamodb_table = "secure-cloud-terraform-tests" 7 | region = "eu-west-3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | required_providers { 4 | aws = { 5 | version = ">= 3.50.0" 6 | } 7 | helm = { 8 | source = "hashicorp/helm" 9 | version = ">=2.3.0" 10 | } 11 | sysdig = { 12 | source = "sysdiglabs/sysdig" 13 | version = ">= 0.5.33" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/fixtures/single-account-apprunner/backend.tf: -------------------------------------------------------------------------------- 1 | # Terraform state storage backend 2 | terraform { 3 | backend "s3" { 4 | bucket = "secure-cloud-terraform-tests" # single examples deploy in qa org/cloudnative account/s3 bucket 5 | key = "aws-single-account-apprunner/terraform.tfstate" 6 | dynamodb_table = "secure-cloud-terraform-tests" 7 | region = "eu-west-3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/single-account-k8s/main.tf: -------------------------------------------------------------------------------- 1 | module "resource_group" { 2 | source = "../../modules/infrastructure/resource-group" 3 | name = var.name 4 | tags = var.tags 5 | } 6 | 7 | module "ssm" { 8 | source = "../../modules/infrastructure/ssm" 9 | name = var.name 10 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 11 | tags = var.tags 12 | } 13 | -------------------------------------------------------------------------------- /modules/infrastructure/resource-group/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_resourcegroups_group" "sysdig_secure_for_cloud" { 2 | 3 | name = var.name 4 | tags = var.tags 5 | 6 | resource_query { 7 | query = < "$path"/aliased-providers.tf.json 15 | done 16 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_user_policy" "general" { 2 | name = var.name 3 | user = data.aws_iam_user.this.user_name 4 | policy = data.aws_iam_policy_document.general.json 5 | } 6 | 7 | data "aws_iam_policy_document" "general" { 8 | statement { 9 | sid = "AllowSSMGetParameter" 10 | effect = "Allow" 11 | actions = ["ssm:GetParameters"] 12 | resources = [var.secure_api_token_secret_arn] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | output "ecs_cluster_name" { 2 | value = aws_ecs_cluster.ecs_cluster.id 3 | description = "ID of the ECS cluster" 4 | } 5 | 6 | output "ecs_vpc_id" { 7 | value = module.vpc.vpc_id 8 | description = "ID of the VPC for the ECS cluster" 9 | } 10 | 11 | output "ecs_vpc_subnets_private_ids" { 12 | value = module.vpc.private_subnets 13 | description = "IDs of the private subnets of the VPC for the ECS cluster" 14 | } 15 | -------------------------------------------------------------------------------- /test/trigger-events/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_iam_policy_document" "flow_log_cloudwatch_assume_role" { 2 | statement { 3 | effect = "Allow" 4 | actions = ["cloudformation:*"] 5 | resources = ["*"] 6 | } 7 | } 8 | 9 | resource "aws_iam_policy" "policy" { 10 | name = "test_policy" 11 | description = "Trigger event policy" 12 | 13 | # Terraform's "jsonencode" function converts a 14 | # Terraform expression result to valid JSON syntax. 15 | policy = data.aws_iam_policy_document.flow_log_cloudwatch_assume_role.json 16 | } 17 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/main.tf: -------------------------------------------------------------------------------- 1 | #------------------------------------- 2 | # general resources 3 | #------------------------------------- 4 | 5 | module "resource_group" { 6 | source = "../../modules/infrastructure/resource-group" 7 | name = var.name 8 | tags = var.tags 9 | } 10 | 11 | module "ssm" { 12 | source = "../../modules/infrastructure/ssm" 13 | name = var.name 14 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 15 | } 16 | -------------------------------------------------------------------------------- /resources/scripts/terraform-clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use from root path ./resources/scripts/terraform-clean.sh 4 | # we don't wanna delete possible ./test state tests 5 | 6 | pushd . 7 | cd examples 8 | find . -name ".terraform" -exec rm -fr {} \; 9 | find . -name "terraform.tfstate*" -exec rm -fr {} \; 10 | find . -name ".terraform.lock.hcl*" -exec rm -fr {} \; 11 | 12 | popd 13 | cd modules 14 | find . -name ".terraform" -exec rm -fr {} \; 15 | find . -name "terraform.tfstate*" -exec rm -fr {} \; 16 | find . -name ".terraform.lock.hcl*" -exec rm -fr {} \; 17 | -------------------------------------------------------------------------------- /examples/single-account-k8s/cloudtrail.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | cloudtrail_deploy = var.cloudtrail_sns_arn == "create" 3 | cloudtrail_sns_arn = var.cloudtrail_sns_arn == "create" ? module.cloudtrail[0].cloudtrail_sns_arn : var.cloudtrail_sns_arn 4 | } 5 | 6 | module "cloudtrail" { 7 | count = local.cloudtrail_deploy ? 1 : 0 8 | source = "../../modules/infrastructure/cloudtrail" 9 | name = var.name 10 | 11 | is_organizational = false 12 | is_multi_region_trail = var.cloudtrail_is_multi_region_trail 13 | cloudtrail_kms_enable = var.cloudtrail_kms_enable 14 | 15 | tags = var.tags 16 | } 17 | -------------------------------------------------------------------------------- /.github/git-chlog/CHANGELOG.tpl.md: -------------------------------------------------------------------------------- 1 | {{ range .Versions }} 2 | {{ range .CommitGroups -}} 3 | ### {{ .Title }} 4 | 5 | {{ range .Commits -}} 6 | * {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} 7 | {{ if .Body }}> {{ .Body }} {{ end }} 8 | {{ end }} 9 | {{ end -}} 10 | 11 | {{- if .RevertCommits -}} 12 | ### Reverts 13 | 14 | {{ range .RevertCommits -}} 15 | * {{ .Revert.Header }} 16 | {{ end }} 17 | {{ end -}} 18 | 19 | {{- if .NoteGroups -}} 20 | {{ range .NoteGroups -}} 21 | ### {{ .Title }} 22 | 23 | {{ range .Notes }} 24 | {{ .Body }} 25 | {{ end }} 26 | {{ end -}} 27 | {{ end -}} 28 | {{ end -}} 29 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/cloudtrail.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | cloudtrail_deploy = var.cloudtrail_sns_arn == "create" 3 | cloudtrail_sns_arn = local.cloudtrail_deploy ? module.cloudtrail[0].cloudtrail_sns_arn : var.cloudtrail_sns_arn 4 | } 5 | 6 | module "cloudtrail" { 7 | count = local.cloudtrail_deploy ? 1 : 0 8 | 9 | source = "../../modules/infrastructure/cloudtrail" 10 | name = var.name 11 | is_organizational = false 12 | is_multi_region_trail = var.cloudtrail_is_multi_region_trail 13 | cloudtrail_kms_enable = var.cloudtrail_kms_enable 14 | 15 | tags = var.tags 16 | } 17 | -------------------------------------------------------------------------------- /test/eks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "k8s_name" { 2 | value = aws_eks_cluster.aws_eks.name 3 | description = "eks cluster name" 4 | } 5 | output "k8s_endpoint" { 6 | value = aws_eks_cluster.aws_eks.endpoint 7 | description = "eks cluster endpoint" 8 | } 9 | 10 | output "k8s_kubeconfig_certificate_authority_data" { 11 | value = aws_eks_cluster.aws_eks.certificate_authority[0].data 12 | description = "eks cluster certificate authority data" 13 | } 14 | 15 | output "k8s_auth_token" { 16 | sensitive = true 17 | value = data.aws_eks_cluster_auth.eks_auth.token 18 | description = "eks cluster auth token" 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/single-account-apprunner/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sysdig_secure_api_token" { 2 | type = string 3 | sensitive = true 4 | description = "Sysdig secure api token" 5 | } 6 | 7 | variable "name" { 8 | type = string 9 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 10 | default = "sfc-test-single-app" 11 | } 12 | 13 | variable "sysdig_secure_url" { 14 | type = string 15 | description = "Sysdig secure endpoint" 16 | default = "https://secure.sysdig.com" 17 | } 18 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail_s3-sns-sqs/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cloudtrail_subscribed_sqs_url" { 2 | value = module.cloudtrail_s3_sns_sqs.cloudtrail_sns_subscribed_sqs_url 3 | description = "URL of the SQS topic subscribed to the SNS of Cloudtrail-S3 bucket" 4 | } 5 | 6 | output "cloudtrail_subscribed_sqs_arn" { 7 | value = module.cloudtrail_s3_sns_sqs.cloudtrail_sns_subscribed_sqs_arn 8 | description = "ARN of the SQS topic subscribed to the SNS of Cloudtrail-S3 bucket" 9 | } 10 | 11 | output "cloudtrail_s3_arn" { 12 | value = data.aws_s3_bucket.cloudtrail_s3.arn 13 | description = "ARN of the SQS topic subscribed to the SNS of Cloudtrail-S3 bucket" 14 | } 15 | -------------------------------------------------------------------------------- /examples/single-account-k8s/credentials.tf: -------------------------------------------------------------------------------- 1 | module "iam_user" { 2 | source = "../../modules/infrastructure/permissions/iam-user" 3 | count = var.deploy_aws_iam_user ? 1 : 0 4 | name = var.name 5 | 6 | deploy_image_scanning = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs 7 | 8 | ssm_secure_api_token_arn = module.ssm.secure_api_token_secret_arn 9 | cloudtrail_s3_bucket_arn = length(module.cloudtrail) > 0 ? module.cloudtrail[0].s3_bucket_arn : "*" 10 | cloudtrail_subscribed_sqs_arn = module.cloud_connector_sqs.cloudtrail_sns_subscribed_sqs_arn 11 | scanning_codebuild_project_arn = length(module.codebuild) > 0 ? module.codebuild[0].project_arn : "*" 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/issues-slack-notify.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: [opened] 4 | name: Issue created Slack Notification 5 | jobs: 6 | slackNotification: 7 | name: Slack Notification 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Slack Notification 12 | uses: rtCamp/action-slack-notify@v2 13 | env: 14 | SLACK_CHANNEL: ws-cloudnative-internal 15 | SLACK_ICON: https://github.com/fluidicon.png 16 | SLACK_MESSAGE: 'An issue has been opened in AWS Terraform repository' 17 | SLACK_TITLE: Issue Created 18 | SLACK_USERNAME: gitHub 19 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} 20 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sfc_user_name" { 2 | type = string 3 | description = "Name of the IAM user to provision permissions" 4 | } 5 | 6 | variable "secure_api_token_secret_arn" { 7 | type = string 8 | description = "ARN of Sysdig Secure API token SSM parameter" 9 | } 10 | 11 | #--------------------------------- 12 | # optionals - with default 13 | #--------------------------------- 14 | 15 | variable "name" { 16 | type = string 17 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 18 | default = "sfc" 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/single-account-apprunner/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | sysdig = { 4 | source = "sysdiglabs/sysdig" 5 | version = ">=0.5.33" 6 | } 7 | aws = { 8 | source = "hashicorp/aws" 9 | } 10 | } 11 | } 12 | 13 | provider "sysdig" { 14 | sysdig_secure_api_token = var.sysdig_secure_api_token 15 | sysdig_secure_url = var.sysdig_secure_url 16 | } 17 | 18 | provider "aws" { 19 | region = "eu-west-1" 20 | } 21 | 22 | module "cloudvision_aws_apprunner_single_account" { 23 | source = "../../../examples/single-account-apprunner" 24 | name = var.name 25 | 26 | deploy_image_scanning_ecr = true 27 | deploy_image_scanning_ecs = true 28 | } 29 | -------------------------------------------------------------------------------- /modules/infrastructure/sqs-sns-subscription/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | type = string 3 | description = "Queue name" 4 | } 5 | 6 | variable "cloudtrail_sns_arn" { 7 | type = string 8 | description = "CloudTrail SNS Topic ARN to subscribe the SQS queue" 9 | } 10 | 11 | variable "tags" { 12 | type = map(string) 13 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 14 | default = { 15 | "product" = "sysdig-secure-for-cloud" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/single-account-ecs/ecs.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | ecs_deploy = var.ecs_cluster_name == "create" 3 | ecs_cluster_name = local.ecs_deploy ? module.ecs_vpc[0].ecs_cluster_name : var.ecs_cluster_name 4 | ecs_vpc_id = local.ecs_deploy ? module.ecs_vpc[0].ecs_vpc_id : var.ecs_vpc_id 5 | ecs_vpc_subnets_private_ids = local.ecs_deploy ? module.ecs_vpc[0].ecs_vpc_subnets_private_ids : var.ecs_vpc_subnets_private_ids 6 | } 7 | 8 | module "ecs_vpc" { 9 | count = local.ecs_deploy ? 1 : 0 10 | 11 | source = "../../modules/infrastructure/ecs-vpc" 12 | name = var.name 13 | ecs_vpc_region_azs = var.ecs_vpc_region_azs 14 | tags = var.tags 15 | } 16 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/iam-user/outputs.tf: -------------------------------------------------------------------------------- 1 | output "sfc_user_name" { 2 | value = aws_iam_user.this.name 3 | description = "Name of the Secure for cloud Provisioned IAM user" 4 | } 5 | 6 | output "sfc_user_arn" { 7 | value = aws_iam_user.this.arn 8 | description = "ARN of the Secure for cloud Provisioned IAM user" 9 | } 10 | 11 | output "sfc_user_access_key_id" { 12 | value = aws_iam_access_key.this.id 13 | description = "Secure for cloud Provisioned user accessKey" 14 | sensitive = true 15 | } 16 | 17 | output "sfc_user_secret_access_key" { 18 | value = aws_iam_access_key.this.secret 19 | description = "Secure for cloud Provisioned user secretAccessKey" 20 | sensitive = true 21 | } 22 | -------------------------------------------------------------------------------- /.github/git-chlog/config.yaml: -------------------------------------------------------------------------------- 1 | style: github 2 | template: CHANGELOG.tpl.md 3 | info: 4 | title: CHANGELOG 5 | repository_url: https://github.com/sysdiglabs/terraform-aws-secure-for-cloud 6 | options: 7 | commits: 8 | commit_groups: 9 | title_maps: 10 | feat: Features 11 | fix: Bug Fixes 12 | perf: Performance Improvements 13 | refactor: Code Refactoring 14 | ci: Continuous Integration 15 | docs: Documentation 16 | chore: Small Modifications 17 | build: Compilation & Dependencies 18 | header: 19 | pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$" 20 | pattern_maps: 21 | - Type 22 | - Scope 23 | - Subject 24 | notes: 25 | keywords: 26 | - BREAKING CHANGE 27 | -------------------------------------------------------------------------------- /test/fixtures/single-account-ecs/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sysdig_secure_api_token" { 2 | type = string 3 | sensitive = true 4 | description = "Sysdig secure api token" 5 | } 6 | 7 | variable "name" { 8 | type = string 9 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 10 | default = "sfctest-single-ecs" 11 | } 12 | 13 | variable "region" { 14 | type = string 15 | description = "Region to be deployed" 16 | default = "eu-west-3" 17 | } 18 | 19 | variable "sysdig_secure_url" { 20 | type = string 21 | description = "Sysdig secure endpoint" 22 | default = "https://secure.sysdig.com" 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/single-account-k8s/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sysdig_secure_api_token" { 2 | type = string 3 | sensitive = true 4 | description = "Sysdig secure api token" 5 | } 6 | 7 | variable "name" { 8 | type = string 9 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 10 | default = "sfc-test-single-k8s" 11 | } 12 | 13 | variable "region" { 14 | type = string 15 | description = "Region to be deployed" 16 | default = "eu-west-3" 17 | } 18 | 19 | variable "sysdig_secure_url" { 20 | type = string 21 | description = "Sysdig secure endpoint" 22 | default = "https://secure.sysdig.com" 23 | } 24 | -------------------------------------------------------------------------------- /examples/organizational/ecs.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | ecs_deploy = var.ecs_cluster_name == "create" 3 | ecs_cluster_name = local.ecs_deploy ? module.ecs_vpc[0].ecs_cluster_name : var.ecs_cluster_name 4 | ecs_vpc_id = local.ecs_deploy ? module.ecs_vpc[0].ecs_vpc_id : var.ecs_vpc_id 5 | ecs_vpc_subnets_private_ids = local.ecs_deploy ? module.ecs_vpc[0].ecs_vpc_subnets_private_ids : var.ecs_vpc_subnets_private_ids 6 | } 7 | 8 | module "ecs_vpc" { 9 | providers = { 10 | aws = aws.member 11 | } 12 | 13 | count = local.ecs_deploy ? 1 : 0 14 | source = "../../modules/infrastructure/ecs-vpc" 15 | 16 | name = var.name 17 | ecs_vpc_region_azs = var.ecs_vpc_region_azs 18 | tags = var.tags 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/single-account-k8s/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | sysdig = { 4 | source = "sysdiglabs/sysdig" 5 | } 6 | aws = { 7 | source = "hashicorp/aws" 8 | } 9 | } 10 | } 11 | 12 | provider "sysdig" { 13 | sysdig_secure_api_token = var.sysdig_secure_api_token 14 | sysdig_secure_url = var.sysdig_secure_url 15 | } 16 | 17 | provider "aws" { 18 | region = var.region 19 | } 20 | 21 | provider "helm" { 22 | kubernetes { 23 | config_path = "~/.kube/config" 24 | } 25 | } 26 | 27 | module "cloudvision_aws_single_account_k8s" { 28 | source = "../../../examples/single-account-k8s" 29 | name = "${var.name}-singlek8s" 30 | 31 | deploy_image_scanning_ecr = true 32 | deploy_image_scanning_ecs = true 33 | } 34 | -------------------------------------------------------------------------------- /resources/scripts/terraform_validate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ensure errexit + failfast 4 | set -o errexit 5 | 6 | # cleanup 7 | echo "cleaning .terraform state" 8 | bash ./resources/terraform-clean.sh 9 | 10 | for dir in $(find . -name 'versions.tf' -not -path '*.terraform*' -exec dirname {} \;) 11 | do 12 | echo validating [$dir] 13 | # skip aliased providers due to terraform validate unresolved bug 14 | # https://github.com/hashicorp/terraform/issues/28490 15 | if [ "$dir" == "examples/organizational" ]; then 16 | echo "skipping validation on [$dir]" 17 | break 18 | fi 19 | pushd . 20 | cd "$dir" 21 | # force init 22 | # https://github.com/antonbabenko/pre-commit-terraform/issues/224 23 | terraform init --upgrade 24 | terraform validate 25 | popd 26 | done 27 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-connector/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sfc_user_name" { 2 | type = string 3 | description = "Name of the IAM user to provision permissions" 4 | } 5 | 6 | variable "cloudtrail_s3_bucket_arn" { 7 | type = string 8 | description = "ARN of cloudtrail s3 bucket" 9 | } 10 | 11 | variable "cloudtrail_subscribed_sqs_arn" { 12 | type = string 13 | description = "ARN of the cloudtrail subscribed sqs's" 14 | } 15 | 16 | 17 | #--------------------------------- 18 | # optionals - with default 19 | #--------------------------------- 20 | 21 | variable "name" { 22 | type = string 23 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 24 | default = "sfc" 25 | } 26 | -------------------------------------------------------------------------------- /modules/infrastructure/resource-group/variables.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------- 2 | # optionals - with default 3 | #--------------------------------- 4 | 5 | variable "name" { 6 | type = string 7 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 8 | default = "sfc" 9 | } 10 | 11 | 12 | variable "tags" { 13 | type = map(string) 14 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 15 | default = { 16 | "product" = "sysdig-secure-for-cloud" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: terraform 4 | root_module_directory: test/fixtures 5 | parallelism: 4 6 | verify_version: false 7 | command_timeout: 1200 8 | 9 | provisioner: 10 | name: terraform 11 | 12 | platforms: 13 | - name: "aws" 14 | 15 | suites: 16 | - name: organizational 17 | driver: 18 | root_module_directory: test/fixtures/organizational 19 | - name: organizational-k8s 20 | driver: 21 | root_module_directory: test/fixtures/organizational-k8s 22 | - name: single-account-apprunner 23 | driver: 24 | root_module_directory: test/fixtures/single-account-apprunner 25 | - name: single-account-ecs 26 | driver: 27 | root_module_directory: test/fixtures/single-account-ecs 28 | - name: single-account-k8s 29 | driver: 30 | root_module_directory: test/fixtures/single-account-k8s 31 | -------------------------------------------------------------------------------- /modules/infrastructure/ssm/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | type = string 3 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 4 | default = "sfc" 5 | } 6 | 7 | variable "sysdig_secure_api_token" { 8 | sensitive = true 9 | type = string 10 | description = "Sysdig Secure API token" 11 | } 12 | 13 | variable "tags" { 14 | type = map(string) 15 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 16 | default = { 17 | "product" = "sysdig-secure-for-cloud" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/single-account-ecs/cloudtrail.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | cloudtrail_deploy = var.cloudtrail_sns_arn == "create" 3 | cloudtrail_sns_arn = local.cloudtrail_deploy ? module.cloudtrail[0].cloudtrail_sns_arn : var.cloudtrail_sns_arn 4 | } 5 | 6 | module "cloudtrail" { 7 | count = local.cloudtrail_deploy ? 1 : 0 8 | source = "../../modules/infrastructure/cloudtrail" 9 | name = var.name 10 | is_organizational = false 11 | is_multi_region_trail = var.cloudtrail_is_multi_region_trail 12 | cloudtrail_kms_enable = var.cloudtrail_kms_enable 13 | s3_bucket_expiration_days = var.cloudtrail_s3_bucket_expiration_days 14 | temporary_s3_bucket_public_block = var.temporary_cloudtrail_s3_bucket_public_block 15 | tags = var.tags 16 | } 17 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sfc_user_name" { 2 | type = string 3 | description = "Name of the IAM user to provision permissions" 4 | } 5 | 6 | variable "cloudtrail_subscribed_sqs_arn" { 7 | type = string 8 | description = "ARN of the cloudtrail subscribed sqs's" 9 | } 10 | 11 | 12 | variable "scanning_codebuild_project_arn" { 13 | type = string 14 | description = "ARN of codebuild to launch the image scanning process" 15 | } 16 | 17 | 18 | #--------------------------------- 19 | # optionals - with default 20 | #--------------------------------- 21 | 22 | variable "name" { 23 | type = string 24 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 25 | default = "sfc" 26 | } 27 | -------------------------------------------------------------------------------- /test/fixtures/organizational/variables.tf: -------------------------------------------------------------------------------- 1 | variable "sysdig_secure_api_token" { 2 | type = string 3 | sensitive = true 4 | description = "Sysdig secure api token" 5 | } 6 | variable "sysdig_secure_for_cloud_member_account_id" { 7 | type = string 8 | description = "organizational member account where the secure-for-cloud workload is going to be deployed" 9 | } 10 | 11 | 12 | 13 | 14 | variable "name" { 15 | type = string 16 | description = "Name is the prefix used in the resources will be created" 17 | default = "sfc-test-org-ecs" 18 | } 19 | 20 | variable "region" { 21 | type = string 22 | description = "Region to be deployed" 23 | default = "eu-west-3" 24 | } 25 | 26 | variable "sysdig_secure_url" { 27 | type = string 28 | description = "Sysdig secure endpoint" 29 | default = "https://secure.sysdig.com" 30 | } 31 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/locals.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | deploy_image_scanning = var.deploy_image_scanning_ecs || var.deploy_image_scanning_ecr || var.deploy_beta_image_scanning_ecr 3 | deploy_image_scanning_with_codebuild = (var.deploy_image_scanning_ecs || var.deploy_image_scanning_ecr) && !var.deploy_beta_image_scanning_ecr 4 | 5 | verify_ssl = var.verify_ssl == "auto" ? length(regexall("https://.*?\\.sysdig(cloud)?.com/?", data.sysdig_secure_connection.current.secure_url)) == 1 : var.verify_ssl == "true" 6 | 7 | # this must satisfy input provided existing cluster ARNs and just created cluster format 8 | # ex. input var: 'foo' 9 | # ex. just created cluster name, gathered through tf data : 'arn:aws:ecs:eu-west-3:425287181461:cluster/foo' 10 | sanitized_cluster_name = coalesce(split("/", join("/", [var.ecs_cluster_name, ""]))[1], var.ecs_cluster_name) 11 | } 12 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/sec-group.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "sg" { 2 | name = var.name 3 | description = "CloudConnector workload Security Group" 4 | 5 | vpc_id = var.ecs_vpc_id 6 | 7 | # Allow outbound DNS traffic over UDP and TCP 8 | # Used by the ECS task to retrieve secrets from SSM 9 | egress { 10 | from_port = 53 11 | protocol = "udp" 12 | to_port = 53 13 | cidr_blocks = ["0.0.0.0/0"] 14 | } 15 | 16 | egress { 17 | from_port = 53 18 | protocol = "tcp" 19 | to_port = 53 20 | cidr_blocks = ["0.0.0.0/0"] 21 | } 22 | 23 | # Allow outbound HTTPS traffic over TCP 24 | # Used by Cloud Connector to send events to https://secure.sysdig.com 25 | egress { 26 | from_port = 443 27 | protocol = "tcp" 28 | to_port = 443 29 | cidr_blocks = ["0.0.0.0/0"] 30 | } 31 | 32 | tags = var.tags 33 | } 34 | -------------------------------------------------------------------------------- /test/fixtures/single-account-ecs/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | sysdig = { 4 | source = "sysdiglabs/sysdig" 5 | version = ">=0.5.33" 6 | } 7 | 8 | aws = { 9 | source = "hashicorp/aws" 10 | } 11 | } 12 | } 13 | 14 | provider "sysdig" { 15 | sysdig_secure_api_token = var.sysdig_secure_api_token 16 | sysdig_secure_url = var.sysdig_secure_url 17 | } 18 | 19 | provider "aws" { 20 | region = var.region 21 | } 22 | 23 | module "cloudvision_aws_single_account_ecs" { 24 | source = "../../../examples/single-account-ecs" 25 | name = "${var.name}-single" 26 | 27 | deploy_image_scanning_ecr = true 28 | deploy_image_scanning_ecs = true 29 | 30 | enable_autoscaling = true 31 | autoscaling_config = { 32 | min_replicas = 1 33 | max_replicas = 4 34 | upscale_threshold = 60 35 | downscale_threshold = 30 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_codebuild_project" "build_project" { 2 | name = "${var.name}-BuildProject" 3 | description = "CodeBuild project which scans images using inline technology" 4 | 5 | service_role = aws_iam_role.service.arn 6 | 7 | artifacts { 8 | type = "NO_ARTIFACTS" 9 | } 10 | 11 | environment { 12 | compute_type = "BUILD_GENERAL1_MEDIUM" 13 | image = "aws/codebuild/standard:3.0" 14 | type = "LINUX_CONTAINER" 15 | privileged_mode = "true" 16 | } 17 | 18 | logs_config { 19 | cloudwatch_logs { 20 | group_name = aws_cloudwatch_log_group.log.name 21 | } 22 | } 23 | 24 | source { 25 | type = "NO_SOURCE" 26 | buildspec = yamlencode({ 27 | version = "0.2" 28 | phases = { 29 | build = { 30 | commands = ["exit"] 31 | } 32 | } 33 | }) 34 | } 35 | 36 | tags = var.tags 37 | } 38 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/main.tf: -------------------------------------------------------------------------------- 1 | # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail 2 | resource "aws_cloudtrail" "cloudtrail" { 3 | 4 | name = var.name 5 | 6 | is_organization_trail = var.is_organizational 7 | 8 | s3_bucket_name = aws_s3_bucket.cloudtrail.id 9 | is_multi_region_trail = var.is_multi_region_trail 10 | 11 | kms_key_id = var.cloudtrail_kms_enable ? aws_kms_key.cloudtrail_kms[0].arn : null 12 | sns_topic_name = aws_sns_topic.cloudtrail.id 13 | 14 | enable_logging = true 15 | enable_log_file_validation = true 16 | include_global_service_events = true 17 | 18 | tags = var.tags 19 | 20 | ## note: seems required to avoid racing conditions (InsufficientSnsTopicPolicyException on cloudtrail creation) /shrug 21 | depends_on = [ 22 | aws_s3_bucket_policy.cloudtrail_s3, 23 | aws_sns_topic_policy.allow_cloudtrail_publish 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/vpc.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "zones" { 2 | } 3 | 4 | # https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest 5 | module "vpc" { 6 | # AC_AWS_0369 7 | #ts:skip=AC_AWS_0369 Cannot be ignored on external module 8 | source = "terraform-aws-modules/vpc/aws" 9 | version = ">=3.14.0" 10 | 11 | name = "${var.name}-vpc" 12 | cidr = "10.0.0.0/16" 13 | 14 | private_subnets = ["10.0.1.0/24", "10.0.2.0/24"] 15 | public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] 16 | map_public_ip_on_launch = false 17 | 18 | azs = length(var.ecs_vpc_region_azs) > 0 ? var.ecs_vpc_region_azs : [ 19 | data.aws_availability_zones.zones.names[0], 20 | data.aws_availability_zones.zones.names[1] 21 | ] 22 | 23 | enable_dns_hostnames = true 24 | enable_dns_support = true 25 | enable_nat_gateway = true 26 | enable_vpn_gateway = false 27 | 28 | tags = var.tags 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | terraform.tfvars 19 | *.tfvars 20 | 21 | # Ignore override files as they are usually used to override resources locally and so 22 | # are not checked in 23 | override.tf 24 | override.tf.json 25 | *_override.tf 26 | *_override.tf.json 27 | 28 | .terraform.lock.hcl 29 | **/.envrc 30 | 31 | *.patch 32 | 33 | # MacOS 34 | .DS_Store 35 | 36 | ## Ruby 37 | ## Environment normalization: 38 | /.bundle/ 39 | /vendor/bundle 40 | /lib/bundler/man/ 41 | 42 | 43 | # test 44 | .kitchen/* 45 | test/fixtures/**/.kitchen/ 46 | test/snippets/* 47 | 48 | # pre-commit workarounds 49 | **/aliased-providers.tf.json 50 | -------------------------------------------------------------------------------- /test/eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "default_vpc_subnets" { 2 | type = list(string) 3 | description = "Default VPC subnets for specified region variable. At least two different AZs are required" 4 | } 5 | 6 | 7 | #--------------------------------- 8 | # optionals - with defaults 9 | #--------------------------------- 10 | 11 | 12 | variable "name" { 13 | type = string 14 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 15 | default = "sfc" 16 | } 17 | 18 | #variable "region" { 19 | # type = string 20 | # default = "eu-central-1" 21 | #} 22 | 23 | variable "tags" { 24 | type = map(string) 25 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 26 | default = { 27 | "product" = "sysdig-secure-for-cloud" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/variables.tf: -------------------------------------------------------------------------------- 1 | variable "secure_api_token_secret_name" { 2 | type = string 3 | description = "Sysdig Secure API token SSM parameter name" 4 | } 5 | 6 | #------------------------------ 7 | # optionals - with defaults 8 | #------------------------------ 9 | variable "cloudwatch_log_retention" { 10 | type = number 11 | default = 30 12 | description = "Days to keep logs from builds" 13 | } 14 | 15 | variable "name" { 16 | type = string 17 | default = "sfc-codebuild" 18 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 19 | } 20 | 21 | variable "tags" { 22 | type = map(string) 23 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 24 | default = { 25 | "product" = "sysdig-secure-for-cloud" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/cloudconnector-config.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | default_config = yamlencode(merge({ 3 | logging = "info" 4 | rules = [] 5 | ingestors = [ 6 | { 7 | cloudtrail-sns-sqs = merge( 8 | { 9 | queueURL = module.cloud_connector_sqs.cloudtrail_sns_subscribed_sqs_url 10 | } 11 | ) 12 | } 13 | ] 14 | }, 15 | { 16 | scanners = local.deploy_image_scanning ? [ 17 | merge( 18 | var.deploy_beta_image_scanning_ecr ? { 19 | aws-ecr-inline = {} 20 | } : {}, 21 | var.deploy_image_scanning_ecr ? { 22 | aws-ecr = { 23 | codeBuildProject = var.build_project_name 24 | secureAPITokenSecretName = var.secure_api_token_secret_name 25 | } 26 | } : {}, 27 | var.deploy_image_scanning_ecs ? { 28 | aws-ecs = { 29 | codeBuildProject = var.build_project_name 30 | secureAPITokenSecretName = var.secure_api_token_secret_name 31 | } 32 | } : {}) 33 | ] : [] 34 | } 35 | )) 36 | } 37 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/variables.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------- 2 | # optionals - with defaults 3 | #--------------------------------- 4 | 5 | # 6 | # vpc configuration 7 | # 8 | 9 | variable "ecs_vpc_region_azs" { 10 | type = list(string) 11 | description = "List of Availability Zones for ECS VPC creation. e.g.: [\"apne1-az1\", \"apne1-az2\"]. If defaulted, two of the default 'aws_availability_zones' datasource will be taken" 12 | default = [] 13 | } 14 | 15 | # 16 | # general 17 | # 18 | variable "name" { 19 | type = string 20 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 21 | default = "sfc" 22 | } 23 | 24 | variable "tags" { 25 | type = map(string) 26 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 27 | default = { 28 | "product" = "sysdig-secure-for-cloud" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail_s3-sns-sqs/variables.tf: -------------------------------------------------------------------------------- 1 | variable "cloudtrail_s3_name" { 2 | type = string 3 | description = "Name of the Cloudtrail S3 bucket" 4 | } 5 | 6 | #--------------------------------- 7 | # optionals - with defaults 8 | #--------------------------------- 9 | 10 | variable "s3_event_notification_filter_prefix" { 11 | type = string 12 | default = "" 13 | description = "S3 Path filter prefix for event notification. Limit the notifications to objects with key starting with specified characters" 14 | } 15 | 16 | # 17 | # general 18 | # 19 | 20 | variable "name" { 21 | type = string 22 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 23 | default = "sfc" 24 | } 25 | 26 | 27 | variable "tags" { 28 | type = map(string) 29 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 30 | default = { 31 | "product" = "sysdig-secure-for-cloud" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/cloud-connector.tf: -------------------------------------------------------------------------------- 1 | resource "helm_release" "cloud_connector" { 2 | 3 | provider = helm 4 | 5 | name = "cloud-connector" 6 | 7 | repository = "https://charts.sysdig.com" 8 | chart = "cloud-connector" 9 | 10 | create_namespace = true 11 | namespace = var.name 12 | 13 | set { 14 | name = "image.pullPolicy" 15 | value = "Always" 16 | } 17 | 18 | set { 19 | name = "sysdig.url" 20 | value = data.sysdig_secure_connection.current.secure_url 21 | } 22 | 23 | set_sensitive { 24 | name = "sysdig.secureAPIToken" 25 | value = data.sysdig_secure_connection.current.secure_api_token 26 | } 27 | 28 | set_sensitive { 29 | name = "aws.accessKeyId" 30 | value = var.aws_access_key_id 31 | } 32 | 33 | set_sensitive { 34 | name = "aws.secretAccessKey" 35 | value = var.aws_secret_access_key 36 | } 37 | 38 | set { 39 | name = "aws.region" 40 | value = data.aws_region.current.name 41 | } 42 | 43 | set { 44 | name = "telemetryDeploymentMethod" 45 | value = "terraform_aws_k8s_org" 46 | } 47 | 48 | values = [ 49 | < 32 | -------------------------------------------------------------------------------- /examples/organizational/diagram-permissions.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Cluster, Diagram, Edge, Node 3 | from diagrams.aws.security import IAM, IAMRole 4 | from diagrams.aws.management import Cloudtrail 5 | from diagrams.aws.storage import S3 6 | from diagrams.aws.compute import ECR 7 | 8 | 9 | with Diagram("Sysdig Secure for Cloud\n(organizational permissions)", filename="diagram-permissions", show=True): 10 | 11 | 12 | with Cluster("member account (sysdig workload)"): 13 | # bench_role = IAMRole(label="Benchmark role") 14 | member_sysdig_role = IAMRole(label="OrganizationAccountAccessRole") 15 | member_sysdig_ecr = ECR("container registry") 16 | member_sysdig_role >> member_sysdig_ecr 17 | 18 | ecs_role = IAMRole(label="ECSTaskRole") 19 | # bench_role - Edge(style="invis") - member_sysdig_ecr 20 | 21 | 22 | with Cluster("member accounts"): 23 | # IAMRole(label="Benchmark role") 24 | 25 | member_role = IAMRole(label="OrganizationAccountAccessRole") 26 | member_ecr = ECR("container registry") 27 | member_role >> member_ecr 28 | 29 | 30 | with Cluster("management account"): 31 | # IAMRole(label="Benchmark role") 32 | sf4c_role = IAMRole(label="SysdigSecureForCloud") 33 | sf4c_role >> Cloudtrail() 34 | sf4c_role >> S3() 35 | 36 | 37 | ecs_role >> sf4c_role 38 | sf4c_role >> member_role 39 | sf4c_role >> member_sysdig_role 40 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/sns_permissions.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | cross_account = data.aws_caller_identity.me.account_id != var.organizational_config.sysdig_secure_for_cloud_member_account_id 3 | } 4 | 5 | 6 | resource "aws_sns_topic_policy" "allow_cloudtrail_publish" { 7 | arn = aws_sns_topic.cloudtrail.arn 8 | policy = data.aws_iam_policy_document.cloudtrail_sns.json 9 | } 10 | 11 | 12 | data "aws_iam_policy_document" "cloudtrail_sns" { 13 | statement { 14 | sid = "AllowCloudtrailPublish" 15 | effect = "Allow" 16 | principals { 17 | identifiers = ["cloudtrail.amazonaws.com"] 18 | type = "Service" 19 | } 20 | actions = ["sns:Publish"] 21 | resources = [aws_sns_topic.cloudtrail.arn] 22 | } 23 | 24 | 25 | # Organizational Requirements 26 | # note; this statement is required to be on the SNS creation, don't move to other module as policies cannot be overriten/exteneded after creation 27 | dynamic "statement" { 28 | for_each = var.is_organizational && local.cross_account ? [1] : [] 29 | content { 30 | sid = "AllowSysdigSecureForCloudSubscribe" 31 | effect = "Allow" 32 | principals { 33 | identifiers = ["arn:aws:iam::${var.organizational_config.sysdig_secure_for_cloud_member_account_id}:role/${var.organizational_config.organizational_role_per_account}"] 34 | type = "AWS" 35 | } 36 | actions = ["sns:Subscribe"] 37 | resources = [aws_sns_topic.cloudtrail.arn] 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "user_arn" { 2 | type = string 3 | description = "ARN of the IAM user to which roles will be added" 4 | } 5 | 6 | variable "cloudtrail_s3_arn" { 7 | type = string 8 | description = "Cloudtrail S3 bucket ARN" 9 | } 10 | 11 | #--------------------------------- 12 | # optionals - with defaults 13 | #--------------------------------- 14 | 15 | variable "deploy_image_scanning" { 16 | type = bool 17 | description = "true/false whether to provision cloud_scanning permissions" 18 | default = true 19 | } 20 | 21 | 22 | variable "name" { 23 | type = string 24 | default = "sfc" 25 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 26 | } 27 | 28 | variable "organizational_role_per_account" { 29 | type = string 30 | default = "OrganizationAccountAccessRole" 31 | description = "Name of the organizational role deployed by AWS in each account of the organization" 32 | } 33 | 34 | variable "tags" { 35 | type = map(string) 36 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 37 | default = { 38 | "product" = "sysdig-secure-for-cloud" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/variables.tf: -------------------------------------------------------------------------------- 1 | variable "cloudtrail_s3_sns_sqs_url" { 2 | type = string 3 | description = "Organization cloudtrail event notification S3-SNS-SQS URL to listen to" 4 | } 5 | 6 | # cloud-connector deployment params 7 | variable "aws_access_key_id" { 8 | sensitive = true 9 | type = string 10 | description = "cloud-connector. aws credentials in order to access required aws resources. aws.accessKeyId" 11 | } 12 | 13 | variable "aws_secret_access_key" { 14 | sensitive = true 15 | type = string 16 | description = "cloud-connector. aws credentials in order to access required aws resources. aws.secretAccessKey" 17 | } 18 | 19 | 20 | #--------------------------------- 21 | # optionals - with defaults 22 | #--------------------------------- 23 | 24 | 25 | # 26 | # general 27 | # 28 | variable "name" { 29 | type = string 30 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 31 | default = "sfc" 32 | } 33 | 34 | variable "tags" { 35 | type = map(string) 36 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 37 | default = { 38 | "product" = "sysdig-secure-for-cloud" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/fixtures/organizational/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | version = ">= 4.0.0" 5 | configuration_aliases = [aws.member] 6 | } 7 | sysdig = { 8 | source = "sysdiglabs/sysdig" 9 | } 10 | } 11 | } 12 | 13 | provider "sysdig" { 14 | sysdig_secure_api_token = var.sysdig_secure_api_token 15 | sysdig_secure_url = var.sysdig_secure_url 16 | } 17 | 18 | provider "aws" { 19 | region = var.region 20 | } 21 | 22 | 23 | provider "aws" { 24 | alias = "member" 25 | region = var.region 26 | assume_role { 27 | # 'OrganizationAccountAccessRole' is the default role created by AWS for management-account users to be able to admin member accounts. 28 | #
https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access.html 29 | role_arn = "arn:aws:iam::${var.sysdig_secure_for_cloud_member_account_id}:role/OrganizationAccountAccessRole" 30 | } 31 | } 32 | 33 | module "cloudvision_aws_organizational" { 34 | providers = { 35 | aws.member = aws.member 36 | } 37 | source = "../../../examples/organizational" 38 | name = var.name 39 | 40 | sysdig_secure_for_cloud_member_account_id = var.sysdig_secure_for_cloud_member_account_id 41 | deploy_image_scanning_ecr = true 42 | deploy_image_scanning_ecs = true 43 | 44 | enable_autoscaling = true 45 | autoscaling_config = { 46 | min_replicas = 1 47 | max_replicas = 4 48 | upscale_threshold = 60 49 | downscale_threshold = 30 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /resources/sfc-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AllowSysdigSQSDeleteAndReceive", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "sqs:DeleteMessage", 9 | "sqs:ReceiveMessage" 10 | ], 11 | "Resource": "" 12 | }, 13 | { 14 | "Sid": "AllowSysdigReadS3", 15 | "Effect": "Allow", 16 | "Action": [ 17 | "s3:GetObject" 18 | ], 19 | "Resource": "/*" 20 | }, 21 | { 22 | "Sid": "AllowSysdigECSTaskDefinition", 23 | "Effect": "Allow", 24 | "Action": [ 25 | "ecs:DescribeTaskDefinition" 26 | ], 27 | "Resource": "*" 28 | }, 29 | { 30 | "Sid": "AllowSysdigCodeBuildStartBuild", 31 | "Effect": "Allow", 32 | "Action": [ 33 | "codebuild:StartBuild" 34 | ], 35 | "Resource": "" 36 | }, 37 | { 38 | "Sid": "AllowSysdigECRActions", 39 | "Effect": "Allow", 40 | "Action": [ 41 | "ecr:GetAuthorizationToken", 42 | "ecr:BatchCheckLayerAvailability", 43 | "ecr:GetDownloadUrlForLayer", 44 | "ecr:GetRepositoryPolicy", 45 | "ecr:DescribeRepositories", 46 | "ecr:ListImages", 47 | "ecr:DescribeImages", 48 | "ecr:BatchGetImage", 49 | "ecr:GetLifecyclePolicy", 50 | "ecr:GetLifecyclePolicyPreview", 51 | "ecr:ListTagsForResource", 52 | "ecr:DescribeImageScanFindings" 53 | ], 54 | "Resource": "*" 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /use-cases/resources/org-three-with-s3-forward.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Cluster, Diagram, Edge, Node 3 | from diagrams.aws.general import General 4 | from diagrams.aws.management import Cloudtrail 5 | from diagrams.aws.integration import SNS 6 | from diagrams.aws.storage import S3 7 | from diagrams.aws.integration import SQS 8 | from diagrams.aws.compute import ECS 9 | from diagrams.aws.security import IAM, IAMRole 10 | 11 | color_event="firebrick" 12 | 13 | with Diagram("Three-Way Cross-Account", filename="org-three-with-s3-forward", show=True): 14 | 15 | with Cluster("management account - cloudtrail"): 16 | cloudtrail = Cloudtrail("cloudtrail\n(no sns activated)") 17 | #org_role = IAM("sfc-SysdigSecureForCloudRole") 18 | 19 | with Cluster("member account - cloudtrail S3 bucket"): 20 | cloudtrail_s3 = S3("cloudtrail-s3") 21 | cloudtrail_sns_sqs = SQS("cloudtrail-s3-sns-sqs\nevent forward") 22 | org_role = IAM("SysdigSecureForCloud-S3AccessRole") 23 | 24 | with Cluster("member account - SFC compute"): 25 | ecs = ECS("sfc") 26 | ecs_role = IAM("sfc-organizational-ECSTaskRole") 27 | ecs - ecs_role 28 | 29 | cloudtrail >> cloudtrail_s3 30 | cloudtrail_s3 >> cloudtrail_sns_sqs 31 | 32 | ecs_role >> Edge(color=color_event, style="dashed", label="sts:AssumeRole") << org_role 33 | ecs_role >> Edge(color=color_event, style="dashed", label="sqs:Receive+Delete") << cloudtrail_sns_sqs 34 | org_role >> Edge(color=color_event, style="dashed", label="s3:GetObject") << cloudtrail_s3 35 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail_s3-sns-sqs/main.tf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------- 2 | # cloudtrail_s3 bucket sns event notification 3 | # -------------------------------------------- 4 | 5 | data "aws_s3_bucket" "cloudtrail_s3" { 6 | bucket = var.cloudtrail_s3_name 7 | } 8 | 9 | 10 | locals { 11 | s3_sns_name = "${var.name}-s3-sns" 12 | } 13 | 14 | 15 | resource "aws_sns_topic" "s3_sns" { 16 | # AC_AWS_0502 17 | # Why: Encrypt SNS with KMS 18 | #ts:skip=AC_AWS_0502 Don't encrypt as far as SNS can be provided by customer 19 | name = local.s3_sns_name 20 | policy = </dev/null 26 | 27 | docs: clean generate-terraform-providers 28 | pre-commit run -a terraform_docs 29 | 30 | lint: terraform-init 31 | pre-commit run -a terraform_validate 32 | pre-commit run -a terraform_tflint 33 | 34 | fmt: 35 | find -name "*.tf" | xargs dirname | uniq | xargs -I% -P0 sh -c 'cd %; terraform fmt' 36 | pre-commit run -a terraform_fmt 37 | -------------------------------------------------------------------------------- /modules/infrastructure/resource-group/README.md: -------------------------------------------------------------------------------- 1 | # AWS Resource Group 2 | 3 | 4 | 5 | ## Requirements 6 | 7 | | Name | Version | 8 | |------|---------| 9 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 10 | | [aws](#requirement\_aws) | >= 3.50.0 | 11 | 12 | ## Providers 13 | 14 | | Name | Version | 15 | |------|---------| 16 | | [aws](#provider\_aws) | >= 3.50.0 | 17 | 18 | ## Modules 19 | 20 | No modules. 21 | 22 | ## Resources 23 | 24 | | Name | Type | 25 | |------|------| 26 | | [aws_resourcegroups_group.sysdig_secure_for_cloud](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | 27 | 28 | ## Inputs 29 | 30 | | Name | Description | Type | Default | Required | 31 | |------|-------------|------|---------|:--------:| 32 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 33 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 34 | 35 | ## Outputs 36 | 37 | No outputs. 38 | 39 | 40 | ## Authors 41 | 42 | Module is maintained and supported by [Sysdig](https://sysdig.com). 43 | 44 | ## License 45 | 46 | Apache 2 Licensed. See LICENSE for full details. 47 | -------------------------------------------------------------------------------- /test/fixtures/organizational-k8s/variables.tf: -------------------------------------------------------------------------------- 1 | variable "cloudtrail_s3_name" { 2 | type = string 3 | description = "Name of the Cloudtrail S3 bucket" 4 | } 5 | 6 | variable "sysdig_secure_api_token" { 7 | type = string 8 | sensitive = true 9 | description = "Sysdig secure api token" 10 | } 11 | 12 | 13 | 14 | #--------------------------------- 15 | # provide variables for testing 16 | #--------------------------------- 17 | 18 | variable "s3_event_notification_filter_prefix" { 19 | type = string 20 | default = "" 21 | description = "S3 Path filter prefix for event notification. Limit the notifications to objects with key starting with specified characters" 22 | } 23 | 24 | variable "org_profile" { 25 | type = string 26 | default = "" 27 | } 28 | 29 | variable "cloudnative_profile" { 30 | type = string 31 | default = "" 32 | } 33 | 34 | variable "org_accessKeyId" { 35 | type = string 36 | sensitive = true 37 | default = "" 38 | } 39 | 40 | variable "org_secretAccessKey" { 41 | type = string 42 | sensitive = true 43 | default = "" 44 | } 45 | 46 | variable "cloudnative_accessKeyId" { 47 | type = string 48 | sensitive = true 49 | default = "" 50 | } 51 | 52 | variable "cloudnative_secretAccessKey" { 53 | type = string 54 | sensitive = true 55 | default = "" 56 | } 57 | 58 | 59 | 60 | #--------------------------------- 61 | # optionals - with defaults 62 | #--------------------------------- 63 | 64 | variable "sysdig_secure_url" { 65 | type = string 66 | description = "Sysdig secure endpoint" 67 | default = "https://secure.sysdig.com" 68 | } 69 | 70 | variable "name" { 71 | type = string 72 | description = "Name is the prefix used in the resources will be created" 73 | default = "sfctest-org-k8s" 74 | } 75 | 76 | variable "region" { 77 | type = string 78 | description = "Region in which the cloudtrail and EKS are deployed. Currently same region is required" 79 | default = "eu-central-1" 80 | } 81 | -------------------------------------------------------------------------------- /.github/workflows/ci-test-cleanup.yaml: -------------------------------------------------------------------------------- 1 | name: CI - Test Cleanup 2 | on: 3 | workflow_dispatch 4 | 5 | concurrency: terraform 6 | 7 | jobs: 8 | cleanup-cloudnative: 9 | name: Test Cleanup 10 | runs-on: ubuntu-latest 11 | env: 12 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_QA_CLOUDNATIVE_ACCESS_KEY_ID }} 13 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_QA_CLOUDNATIVE_SECRET_ACCESS_KEY }} 14 | AWS_REGION: ${{ secrets.AWS_REGION }} 15 | TF_VAR_sysdig_secure_url: https://secure.sysdig.com 16 | TF_VAR_sysdig_secure_api_token: ${{secrets.KUBELAB_SECURE_API_TOKEN}} 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v2 20 | 21 | - uses: ruby/setup-ruby@v1 22 | with: 23 | ruby-version: 2.7 24 | bundler-cache: true 25 | - name: Create kind cluster # this is not really needed but kitchen requires it 26 | uses: helm/kind-action@v1.2.0 27 | with: 28 | wait: 120s 29 | - name: Destroy resources 30 | run: bundle exec kitchen destroy single 31 | 32 | cleanup-org: 33 | name: Test Cleanup Org 34 | runs-on: ubuntu-latest 35 | env: 36 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_QA_MANAGED_ACCESS_KEY_ID }} 37 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_QA_MANAGED_SECRET_ACCESS_KEY }} 38 | AWS_REGION: ${{ secrets.AWS_REGION }} 39 | TF_VAR_sysdig_secure_for_cloud_member_account_id: ${{ secrets.AWS_QA_CLOUDNATIVE_ACCOUNT_ID }} 40 | TF_VAR_sysdig_secure_url: https://secure.sysdig.com 41 | TF_VAR_sysdig_secure_api_token: ${{secrets.KUBELAB_SECURE_API_TOKEN}} 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v2 45 | 46 | - uses: ruby/setup-ruby@v1 47 | with: 48 | ruby-version: 2.7 49 | bundler-cache: true 50 | - name: Create kind cluster # this is not really needed but kitchen requires it 51 | uses: helm/kind-action@v1.2.0 52 | with: 53 | wait: 120s 54 | - name: Destroy resources 55 | run: bundle exec kitchen destroy organizational 56 | -------------------------------------------------------------------------------- /examples/organizational/permissions.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | # only deploy org-management-account lvl role if scanning is deployed and we're not overriding S3Role 3 | # FIXME. main.tf#72 if scanning is activated, using 'cloudtrail_s3_role_arn' won't work, FR: need to provision 2 roles in cloud-connector 4 | deploy_org_management_sysdig_role = var.deploy_image_scanning_ecs || var.deploy_image_scanning_ecr || var.existing_cloudtrail_config.cloudtrail_s3_sns_sqs_arn == null 5 | } 6 | 7 | module "secure_for_cloud_role" { 8 | count = local.deploy_org_management_sysdig_role ? 1 : 0 9 | source = "../../modules/infrastructure/permissions/org-role-ecs" 10 | providers = { 11 | aws.member = aws.member 12 | } 13 | name = var.name 14 | 15 | cloudtrail_s3_arn = local.cloudtrail_s3_arn 16 | cloudconnector_ecs_task_role_name = aws_iam_role.connector_ecs_task.name 17 | organizational_role_per_account = var.organizational_member_default_admin_role 18 | 19 | tags = var.tags 20 | depends_on = [aws_iam_role.connector_ecs_task] 21 | } 22 | 23 | 24 | # ----------------------------------------------------------------- 25 | # secure_for_cloud_role <-> ecs_role trust relationship 26 | # note: 27 | # - definition of a ROOT lvl secure_for_cloud_connector_ecs_tas_role to avoid cyclic dependencies 28 | # - duplicated in ../../modules/services/cloud-connector-ecs/permissions.tf 29 | # ----------------------------------------------------------------- 30 | resource "aws_iam_role" "connector_ecs_task" { 31 | provider = aws.member 32 | name = "${var.name}-${var.connector_ecs_task_role_name}" 33 | assume_role_policy = data.aws_iam_policy_document.task_assume_role.json 34 | path = "/" 35 | tags = var.tags 36 | } 37 | 38 | 39 | data "aws_iam_policy_document" "task_assume_role" { 40 | provider = aws.member 41 | statement { 42 | effect = "Allow" 43 | principals { 44 | identifiers = ["ecs-tasks.amazonaws.com"] 45 | type = "Service" 46 | } 47 | actions = ["sts:AssumeRole"] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-eks/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "secure_for_cloud_role" { 2 | name = "${var.name}-SysdigSecureForCloudRole" 3 | assume_role_policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_trusted.json 4 | tags = var.tags 5 | } 6 | 7 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_trusted" { 8 | statement { 9 | effect = "Allow" 10 | principals { 11 | type = "AWS" 12 | identifiers = [ 13 | var.user_arn 14 | ] 15 | } 16 | actions = ["sts:AssumeRole"] 17 | } 18 | } 19 | 20 | # ------------------------------ 21 | # enable cloudtrail_s3 RO access 22 | # ------------------------------ 23 | 24 | resource "aws_iam_role_policy" "sysdig_secure_for_cloud_role_s3" { 25 | name = "${var.name}-AllowCloudtrailS3Policy" 26 | role = aws_iam_role.secure_for_cloud_role.id 27 | policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_s3.json 28 | } 29 | 30 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_s3" { 31 | statement { 32 | effect = "Allow" 33 | actions = [ 34 | "s3:ListBucket", 35 | "s3:GetObject" 36 | ] 37 | resources = [ 38 | var.cloudtrail_s3_arn, 39 | "${var.cloudtrail_s3_arn}/*" 40 | ] 41 | } 42 | } 43 | 44 | 45 | # ------------------------------ 46 | # enable image-scanning on member-account repositories 47 | # ------------------------------ 48 | resource "aws_iam_role_policy" "sysdig_secure_for_cloud_role_assume_role" { 49 | count = var.deploy_image_scanning ? 1 : 0 50 | name = "${var.name}-AllowAssumeRoleInChildAccounts" 51 | role = aws_iam_role.secure_for_cloud_role.id 52 | policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_assume_role[0].json 53 | } 54 | 55 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_assume_role" { 56 | count = var.deploy_image_scanning ? 1 : 0 57 | statement { 58 | effect = "Allow" 59 | actions = [ 60 | "sts:AssumeRole", 61 | ] 62 | resources = [ 63 | "arn:aws:iam::*:role/${var.organizational_role_per_account}" 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /DecisionRecord.md: -------------------------------------------------------------------------------- 1 | # DecisionRecord 2 | 3 | > A [Decision record (DR)](https://github.com/joelparkerhenderson/decision-record) is a way to initiate, debate, and archive an important choice, along with its context and consequences. 4 | 5 | Some ideas that would fit in the DR 6 | - global refactorings 7 | - current known limitations 8 | - ... 9 | 10 | **Note: Currently, this DR apply to all Terraform Modules (AWS,GCP and Azure)** 11 | 12 |
13 | 14 | ## 2022 - Remove configuration buckets 15 | 16 | Previously [CloudConnector configuration file](https://charts.sysdig.com/charts/cloud-connector/#configuration) was stored on each cloud storage service. 17 | In order to spin as least resources as possible on customer's infra, we decided to inline this configuration with a base64-encoded `env` var. 18 | 19 | - pros 20 | - less resources on customer 21 | - cons 22 | - modifying configuration (the most common use-case is to lower logs for troubleshooting purpose) is more complicated for the customer 23 | 24 | 25 | ## 2021 - Terraform Modules version pinned to `latest` 26 | 27 | Because we're in fast cycle-releases (v0.x), we don't support backward compatibility and want customer to use latest version. 28 | That's why in Github snippets, and Sysig Secure snippets, we don't use the `version` attirubte of the terraform modules. 29 | 30 | Still, customer wants to pin the terraform module version, they can do so, by using 31 | 32 | ```terraform 33 | module "secure-for-cloud" { 34 | source = "sysdiglabs/secure-for-cloud/aws" 35 | version = "0.9.6" 36 | ... 37 | } 38 | ``` 39 | 40 | Upgrade guideliness are offered in main READMEs. 41 | 42 | 43 | ## 2021 - CloudConnector image version pinned to `latest` 44 | 45 | Not discussed the pro/cons, but currently 46 | 47 | - pros 48 | - if we fix somethiing in cloud-connector customer just has to restart the compute service 49 | - cons 50 | - if required, there is no easy way of pinning the cloud-connector version 51 | 52 | **Possible future actions** 53 | - Expose a variable throught he examples to let customer select cloud-connector version? This can also be done in runtime modifying compute service defintion. 54 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/codebuild-security.tf: -------------------------------------------------------------------------------- 1 | data "aws_region" "current" {} 2 | data "aws_caller_identity" "me" {} 3 | data "aws_partition" "current_partition" {} 4 | data "aws_ssm_parameter" "sysdig_secure_api_token" { 5 | name = var.secure_api_token_secret_name 6 | } 7 | 8 | resource "aws_iam_role" "service" { 9 | name = "${var.name}-ECRScanningRole" 10 | assume_role_policy = data.aws_iam_policy_document.service_assume_role.json 11 | path = "/" 12 | tags = var.tags 13 | } 14 | 15 | data "aws_iam_policy_document" "service_assume_role" { 16 | statement { 17 | effect = "Allow" 18 | principals { 19 | identifiers = ["codebuild.amazonaws.com"] 20 | type = "Service" 21 | } 22 | actions = ["sts:AssumeRole"] 23 | } 24 | } 25 | 26 | resource "aws_iam_role_policy" "logs_publisher" { 27 | name = "LogsPublisher" 28 | role = aws_iam_role.service.id 29 | policy = data.aws_iam_policy_document.logs_publisher.json 30 | } 31 | 32 | data "aws_iam_policy_document" "logs_publisher" { 33 | statement { 34 | effect = "Allow" 35 | actions = [ 36 | "logs:CreateLogStream", 37 | "logs:PutLogEvents" 38 | ] 39 | resources = [ 40 | "arn:${data.aws_partition.current_partition.id}:logs:${data.aws_region.current.name}:${data.aws_caller_identity.me.account_id}:log-group:${aws_codebuild_project.build_project.logs_config[0].cloudwatch_logs[0].group_name}", 41 | "arn:${data.aws_partition.current_partition.id}:logs:${data.aws_region.current.name}:${data.aws_caller_identity.me.account_id}:log-group:${aws_codebuild_project.build_project.logs_config[0].cloudwatch_logs[0].group_name}:*" 42 | ] 43 | } 44 | } 45 | 46 | resource "aws_iam_role_policy" "read_parameters" { 47 | name = "ReadParameters" 48 | policy = data.aws_iam_policy_document.task_read_parameters.json 49 | role = aws_iam_role.service.id 50 | } 51 | data "aws_iam_policy_document" "task_read_parameters" { 52 | statement { 53 | effect = "Allow" 54 | actions = [ 55 | "ssm:GetParameters" 56 | ] 57 | resources = [data.aws_ssm_parameter.sysdig_secure_api_token.arn] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_user_policy" "cloud_scanner" { 2 | name = "${var.name}-cs" 3 | user = data.aws_iam_user.this.user_name 4 | policy = data.aws_iam_policy_document.cloud_scanner.json 5 | } 6 | 7 | data "aws_iam_policy_document" "cloud_scanner" { 8 | 9 | statement { 10 | sid = "AllowReadWriteCloudtrailSubscribedSQS" 11 | effect = "Allow" 12 | actions = [ 13 | "sqs:ReceiveMessage", 14 | "sqs:DeleteMessage" 15 | ] 16 | resources = [var.cloudtrail_subscribed_sqs_arn] 17 | } 18 | 19 | statement { 20 | sid = "AllowScanningCodeBuildStartBuild" 21 | effect = "Allow" 22 | actions = [ 23 | "codebuild:StartBuild" 24 | ] 25 | resources = [var.scanning_codebuild_project_arn] 26 | } 27 | 28 | 29 | statement { 30 | sid = "AllowScanningECRRead" 31 | effect = "Allow" 32 | actions = [ 33 | "ecr:GetAuthorizationToken", 34 | "ecr:BatchCheckLayerAvailability", 35 | "ecr:GetDownloadUrlForLayer", 36 | "ecr:GetRepositoryPolicy", 37 | "ecr:DescribeRepositories", 38 | "ecr:ListImages", 39 | "ecr:DescribeImages", 40 | "ecr:BatchGetImage", 41 | "ecr:GetLifecyclePolicy", 42 | "ecr:GetLifecyclePolicyPreview", 43 | "ecr:ListTagsForResource", 44 | "ecr:DescribeImageScanFindings" 45 | ] 46 | resources = ["*"] 47 | # resources = var.is_organizational ? ["arn:aws:ecr:*:*:repository/*", "arn:aws:ecr-public::*:repository/*", "arn:aws:ecr-public::*:registry/*"] : ["arn:aws:ecr-public::${data.aws_caller_identity.me.account_id}:repository/*", "arn:aws:ecr-public::${data.aws_caller_identity.me.account_id}:repository/*", "arn:aws:ecr-public::${data.aws_caller_identity.me.account_id}:registry/*"]O. make an input-var out of this, so user can pin it to its own ECR ARN's 48 | } 49 | 50 | statement { 51 | sid = "AllowScanningDescribeECSTask" 52 | effect = "Allow" 53 | actions = [ 54 | "ecs:DescribeTaskDefinition" 55 | ] 56 | resources = ["*"] 57 | #resources = [var.is_organizational?"arn:aws:ecs:*:425287181461:cluster/*":var.ecs_cluster_name] # TODO pin-down 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/main.tf: -------------------------------------------------------------------------------- 1 | #------------------------------------- 2 | # general resources 3 | #------------------------------------- 4 | module "resource_group" { 5 | source = "../../modules/infrastructure/resource-group" 6 | name = var.name 7 | tags = var.tags 8 | } 9 | 10 | module "ssm" { 11 | source = "../../modules/infrastructure/ssm" 12 | name = var.name 13 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 14 | tags = var.tags 15 | } 16 | 17 | 18 | #------------------------------------- 19 | # cloud-connector 20 | #------------------------------------- 21 | module "codebuild" { 22 | count = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs ? 1 : 0 23 | 24 | source = "../../modules/infrastructure/codebuild" 25 | name = "${var.name}-codebuild" 26 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 27 | 28 | tags = var.tags 29 | # note. this is required to avoid race conditions 30 | depends_on = [module.ssm] 31 | } 32 | 33 | module "cloud_connector" { 34 | source = "../../modules/services/cloud-connector-apprunner" 35 | name = "${var.name}-cloudconnector" 36 | 37 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 38 | sysdig_secure_url = data.sysdig_secure_connection.current.secure_url 39 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 40 | secure_api_token_secret_arn = module.ssm.secure_api_token_secret_arn 41 | 42 | build_project_arn = length(module.codebuild) == 1 ? module.codebuild[0].project_arn : "na" 43 | build_project_name = length(module.codebuild) == 1 ? module.codebuild[0].project_name : "na" 44 | 45 | cloudconnector_ecr_image_uri = var.cloudconnector_ecr_image_uri 46 | 47 | 48 | deploy_beta_image_scanning_ecr = var.deploy_beta_image_scanning_ecr 49 | deploy_image_scanning_ecr = var.deploy_image_scanning_ecr 50 | deploy_image_scanning_ecs = var.deploy_image_scanning_ecs 51 | 52 | cloudtrail_sns_arn = local.cloudtrail_sns_arn 53 | tags = var.tags 54 | } 55 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-connector/README.md: -------------------------------------------------------------------------------- 1 | # Permissions :: Cloud Connector 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 9 | | [aws](#requirement\_aws) | >= 3.50.0 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 3.50.0 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_iam_user_policy.cloud_connector](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource | 26 | | [aws_iam_policy_document.cloud_connector](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 27 | | [aws_iam_user.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_user) | data source | 28 | 29 | ## Inputs 30 | 31 | | Name | Description | Type | Default | Required | 32 | |------|-------------|------|---------|:--------:| 33 | | [cloudtrail\_s3\_bucket\_arn](#input\_cloudtrail\_s3\_bucket\_arn) | ARN of cloudtrail s3 bucket | `string` | n/a | yes | 34 | | [cloudtrail\_subscribed\_sqs\_arn](#input\_cloudtrail\_subscribed\_sqs\_arn) | ARN of the cloudtrail subscribed sqs's | `string` | n/a | yes | 35 | | [sfc\_user\_name](#input\_sfc\_user\_name) | Name of the IAM user to provision permissions | `string` | n/a | yes | 36 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 37 | 38 | ## Outputs 39 | 40 | No outputs. 41 | 42 | 43 | ## Authors 44 | 45 | Module is maintained and supported by [Sysdig](https://sysdig.com). 46 | 47 | ## License 48 | 49 | Apache 2 Licensed. See LICENSE for full details. 50 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/general/README.md: -------------------------------------------------------------------------------- 1 | # Permissions :: General 2 | 3 | General permissions that apply to both cloud-connector and cloud-scanning modules 4 | - Currently this only applies to the capability of reading the Secure API Token from the Key Management Service 5 | 6 | 7 | ## Requirements 8 | 9 | | Name | Version | 10 | |------|---------| 11 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 12 | | [aws](#requirement\_aws) | >= 3.50.0 | 13 | 14 | ## Providers 15 | 16 | | Name | Version | 17 | |------|---------| 18 | | [aws](#provider\_aws) | >= 3.50.0 | 19 | 20 | ## Modules 21 | 22 | No modules. 23 | 24 | ## Resources 25 | 26 | | Name | Type | 27 | |------|------| 28 | | [aws_iam_user_policy.general](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource | 29 | | [aws_iam_policy_document.general](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 30 | | [aws_iam_user.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_user) | data source | 31 | 32 | ## Inputs 33 | 34 | | Name | Description | Type | Default | Required | 35 | |------|-------------|------|---------|:--------:| 36 | | [secure\_api\_token\_secret\_arn](#input\_secure\_api\_token\_secret\_arn) | ARN of Sysdig Secure API token SSM parameter | `string` | n/a | yes | 37 | | [sfc\_user\_name](#input\_sfc\_user\_name) | Name of the IAM user to provision permissions | `string` | n/a | yes | 38 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 39 | 40 | ## Outputs 41 | 42 | No outputs. 43 | 44 | 45 | ## Authors 46 | 47 | Module is maintained and supported by [Sysdig](https://sysdig.com). 48 | 49 | ## License 50 | 51 | Apache 2 Licensed. See LICENSE for full details. 52 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/cloud-scanning/README.md: -------------------------------------------------------------------------------- 1 | # Permissions :: Cloud Scanning 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 9 | | [aws](#requirement\_aws) | >= 3.50.0 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 3.50.0 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_iam_user_policy.cloud_scanner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource | 26 | | [aws_iam_policy_document.cloud_scanner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 27 | | [aws_iam_user.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_user) | data source | 28 | 29 | ## Inputs 30 | 31 | | Name | Description | Type | Default | Required | 32 | |------|-------------|------|---------|:--------:| 33 | | [cloudtrail\_subscribed\_sqs\_arn](#input\_cloudtrail\_subscribed\_sqs\_arn) | ARN of the cloudtrail subscribed sqs's | `string` | n/a | yes | 34 | | [scanning\_codebuild\_project\_arn](#input\_scanning\_codebuild\_project\_arn) | ARN of codebuild to launch the image scanning process | `string` | n/a | yes | 35 | | [sfc\_user\_name](#input\_sfc\_user\_name) | Name of the IAM user to provision permissions | `string` | n/a | yes | 36 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 37 | 38 | ## Outputs 39 | 40 | No outputs. 41 | 42 | 43 | ## Authors 44 | 45 | Module is maintained and supported by [Sysdig](https://sysdig.com). 46 | 47 | ## License 48 | 49 | Apache 2 Licensed. See LICENSE for full details. 50 | -------------------------------------------------------------------------------- /use-cases/resources/org-three-way-with-sns.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Cluster, Diagram, Edge, Node 3 | from diagrams.aws.general import General 4 | from diagrams.aws.management import Cloudtrail 5 | from diagrams.aws.integration import SNS 6 | from diagrams.aws.storage import S3 7 | from diagrams.aws.integration import SQS 8 | from diagrams.aws.compute import ECS 9 | from diagrams.aws.compute import EKS 10 | from diagrams.aws.security import IAM, IAMRole 11 | from diagrams.k8s.group import Namespace 12 | from diagrams.k8s.compute import Deployment 13 | from diagrams.custom import Custom 14 | 15 | color_event="firebrick" 16 | 17 | with Diagram("Organizational Three-Way Cross-Account Setup", filename="org-three-way-with-sns", show=True): 18 | 19 | 20 | with Cluster("AWS account (sysdig)", graph_attr={"bgcolor": "lightblue"}): 21 | sds = Custom("Sysdig Secure", "../../resources/diag-sysdig-icon.png") 22 | bench = General("Cloud Bench") 23 | sds >> Edge(label="schedule on rand rand * * *") >> bench 24 | 25 | with Cluster("AWS Organization"): 26 | with Cluster("account - management"): 27 | cloudtrail = Cloudtrail("cloudtrail") 28 | cloudtrail_sns = SNS("cloudtrail-sns") 29 | 30 | cloudtrail - cloudtrail_sns 31 | 32 | with Cluster("account2 - logging"): 33 | cloudtrail_s3 = S3("cloudtrail-s3") 34 | s3_role = IAM("SysdigS3AccessRole") 35 | 36 | with Cluster("account - security"): 37 | with Cluster("EKS/ECS Cluster"): 38 | cloud_connector = Deployment("cloud-connector") 39 | cluster_role = IAM("SysdigComputeRole") 40 | cloudtrail_sns_sqs = SQS("cloudtrail-sns-sqs") 41 | cloud_connector - cluster_role 42 | 43 | cloudtrail - cloudtrail_s3 44 | cloudtrail_sns - cloudtrail_sns_sqs 45 | 46 | cluster_role >> Edge(color=color_event, style="dashed", xlabel="sts:AssumeRole\n+TrustedEntity") << s3_role 47 | cluster_role >> Edge(color=color_event, style="dashed", label="sqs:Receive+Delete") << cloudtrail_sns_sqs 48 | s3_role >> Edge(color=color_event, style="dashed", label="s3:GetObject") << cloudtrail_s3 49 | 50 | with Cluster("account(s) - compliance"): 51 | ccBenchRoleOnEachProject = IAM("Sysdig Compliance Role\n(aws:SecurityAudit policy)") 52 | bench >> ccBenchRoleOnEachProject 53 | -------------------------------------------------------------------------------- /test/fixtures/organizational-k8s/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | sysdig = { 4 | source = "sysdiglabs/sysdig" 5 | } 6 | aws = { 7 | source = "hashicorp/aws" 8 | } 9 | } 10 | } 11 | 12 | provider "sysdig" { 13 | sysdig_secure_api_token = var.sysdig_secure_api_token 14 | sysdig_secure_url = var.sysdig_secure_url 15 | } 16 | 17 | provider "aws" { 18 | alias = "admin" 19 | profile = var.org_profile 20 | access_key = var.org_accessKeyId 21 | secret_key = var.org_secretAccessKey 22 | region = var.region 23 | } 24 | 25 | provider "aws" { 26 | alias = "cloudnative" 27 | profile = var.cloudnative_profile 28 | access_key = var.cloudnative_accessKeyId 29 | secret_key = var.cloudnative_secretAccessKey 30 | region = var.region 31 | } 32 | 33 | provider "helm" { 34 | kubernetes { 35 | config_path = "~/.kube/config" 36 | } 37 | } 38 | 39 | module "cloudtrail_s3_sns_sqs" { 40 | providers = { 41 | aws = aws.admin 42 | } 43 | source = "../../../modules/infrastructure/cloudtrail_s3-sns-sqs" 44 | cloudtrail_s3_name = var.cloudtrail_s3_name 45 | s3_event_notification_filter_prefix = var.s3_event_notification_filter_prefix 46 | name = "${var.name}-orgk8s" 47 | } 48 | 49 | 50 | module "org_user" { 51 | providers = { 52 | aws = aws.admin 53 | } 54 | source = "../../../modules/infrastructure/permissions/iam-user" 55 | deploy_image_scanning = false 56 | cloudtrail_s3_bucket_arn = module.cloudtrail_s3_sns_sqs.cloudtrail_s3_arn 57 | cloudtrail_subscribed_sqs_arn = module.cloudtrail_s3_sns_sqs.cloudtrail_subscribed_sqs_arn 58 | name = "${var.name}-orgk8s" 59 | } 60 | 61 | 62 | resource "time_sleep" "wait" { 63 | depends_on = [module.org_user] 64 | create_duration = "5s" 65 | } 66 | 67 | # ------------------- 68 | # actual use case 69 | # ------------------- 70 | 71 | module "org_k8s_threat_reuse_cloudtrail" { 72 | providers = { 73 | aws = aws.cloudnative 74 | } 75 | source = "../../../examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3" 76 | name = var.name 77 | 78 | cloudtrail_s3_sns_sqs_url = module.cloudtrail_s3_sns_sqs.cloudtrail_subscribed_sqs_url 79 | 80 | aws_access_key_id = module.org_user.sfc_user_access_key_id 81 | aws_secret_access_key = module.org_user.sfc_user_secret_access_key 82 | 83 | depends_on = [module.org_user.sfc_user_arn, time_sleep.wait] 84 | } 85 | -------------------------------------------------------------------------------- /use-cases/single-existing-cloudtrail.md: -------------------------------------------------------------------------------- 1 | # Single Account with Existing Cloudtrail 2 | 3 | ## Overview 4 | 5 | ### User Setup 6 | 7 | - [X] Single Account setup 8 | - [X] Pre-existing resources 9 | - [X] CloudTrail 10 | - [ ] Kubernetes cluster to deploy Sysdig for Cloud workload 11 | - [ ] ECS cluster with VPC/subnet for the Sysdig for Cloud deployment 12 | 13 | ### Sysdig Secure For Cloud Features 14 | 15 | - [X] Threat Detection 16 | - [X] all accounts of the organization (management account included) 17 | - [ ] Image Scanning (WIP?) 18 | - [ ] ECR pushed images 19 | - [ ] ECS running images 20 | - [ ] CSPM/Compliance (WIP?) 21 | - [ ] CIEM (WIP?) 22 | 23 | ## Preparation 24 | 25 | For this use case, you will use the [`./examples/single-account-ecs`](./examples/single-account-ecs/README.md) setup. In order for this setup to work, several roles and permissions are required. Before proceeding, see the [readme](./examples/single-account-ecs/README.md) and check whether you comply with the requirements. 26 | 27 | Contact Sysdig for support. 28 | 29 | ## Installation 30 | 31 | Use the [`single-account`](./examples/single-account-ecs/README.md) example with the `cloudtrail_sns_arn` parameter: 32 | 33 | 63 | 64 | ```terraform 65 | terraform { 66 | required_providers { 67 | sysdig = { 68 | source = "sysdiglabs/sysdig" 69 | } 70 | } 71 | } 72 | 73 | provider "sysdig" { 74 | sysdig_secure_url = "" 75 | sysdig_secure_api_token = "" 76 | } 77 | 78 | provider "aws" { 79 | region = "" 80 | } 81 | 82 | module "sysdig-sfc" { 83 | source = "sysdiglabs/secure-for-cloud/aws//examples/single-account-ecs" 84 | name = "sysdig-sfc" 85 | 86 | cloudtrail_sns_arn = "" 87 | } 88 | ``` 89 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | #--------------------------------- 4 | # optionals - with defaults 5 | #--------------------------------- 6 | 7 | 8 | # 9 | # cloudtrail configuration 10 | # 11 | variable "cloudtrail_sns_arn" { 12 | type = string 13 | default = "create" 14 | description = "ARN of a pre-existing cloudtrail_sns. If defaulted, a new cloudtrail will be created. ARN of a pre-existing cloudtrail_sns. If defaulted, a new cloudtrail will be created. If specified, sysdig deployment account and region must match with the specified SNS" 15 | } 16 | 17 | variable "cloudtrail_is_multi_region_trail" { 18 | type = bool 19 | default = true 20 | description = "true/false whether cloudtrail will ingest multiregional events" 21 | } 22 | 23 | variable "cloudtrail_kms_enable" { 24 | type = bool 25 | default = true 26 | description = "true/false whether cloudtrail delivered events to S3 should persist encrypted" 27 | } 28 | 29 | # 30 | # scanning configuration 31 | # 32 | 33 | variable "deploy_beta_image_scanning_ecr" { 34 | type = bool 35 | description = "true/false whether to deploy the beta image scanning on ECR pushed images (experimental and unsupported)" 36 | default = false 37 | } 38 | 39 | variable "deploy_image_scanning_ecr" { 40 | type = bool 41 | description = "true/false whether to deploy the image scanning on ECR pushed images" 42 | default = false 43 | } 44 | 45 | variable "deploy_image_scanning_ecs" { 46 | type = bool 47 | description = "true/false whether to deploy the image scanning on ECS running images" 48 | default = false 49 | } 50 | 51 | # 52 | # general 53 | # 54 | 55 | variable "name" { 56 | type = string 57 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 58 | default = "sfc" 59 | } 60 | 61 | variable "tags" { 62 | type = map(string) 63 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 64 | default = { 65 | "product" = "sysdig-secure-for-cloud" 66 | } 67 | } 68 | 69 | ######## 70 | variable "cloudconnector_ecr_image_uri" { 71 | type = string 72 | description = "URI to cloudconnectors image on ECR" 73 | default = "public.ecr.aws/o5x4u2t4/cloud-connector:latest" 74 | } 75 | -------------------------------------------------------------------------------- /examples/single-account-k8s/variables.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------- 2 | # optionals - with defaults 3 | #--------------------------------- 4 | 5 | # 6 | # cloudtrail configuration 7 | # 8 | 9 | variable "cloudtrail_sns_arn" { 10 | type = string 11 | default = "create" 12 | description = "ARN of a pre-existing cloudtrail_sns. If defaulted, a new cloudtrail will be created. If specified, deployment region must match Cloudtrail S3 bucket region" 13 | } 14 | 15 | variable "cloudtrail_is_multi_region_trail" { 16 | type = bool 17 | default = true 18 | description = "true/false whether cloudtrail will ingest multiregional events. testing/economization purpose. " 19 | } 20 | 21 | variable "cloudtrail_kms_enable" { 22 | type = bool 23 | default = true 24 | description = "true/false whether s3 should be encrypted. testing/economization purpose." 25 | } 26 | 27 | variable "name" { 28 | type = string 29 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 30 | default = "sfc" 31 | } 32 | 33 | variable "tags" { 34 | type = map(string) 35 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 36 | default = { 37 | "product" = "sysdig-secure-for-cloud" 38 | } 39 | } 40 | 41 | # 42 | # scanning configuration 43 | # 44 | 45 | variable "deploy_beta_image_scanning_ecr" { 46 | type = bool 47 | description = "true/false whether to deploy the beta image scanning on ECR pushed images (experimental and unsupported)" 48 | default = false 49 | } 50 | 51 | variable "deploy_image_scanning_ecr" { 52 | type = bool 53 | description = "true/false whether to deploy the image scanning on ECR pushed images" 54 | default = false 55 | } 56 | 57 | variable "deploy_image_scanning_ecs" { 58 | type = bool 59 | description = "true/false whether to deploy the image scanning on ECS running images" 60 | default = false 61 | } 62 | 63 | 64 | # 65 | # aws iam user configuration 66 | # 67 | variable "deploy_aws_iam_user" { 68 | type = bool 69 | description = "true/false whether to deploy an iam user. if set to false, check [required role permissions](https://github.com/sysdiglabs/terraform-aws-secure-for-cloud/blob/master/resources/policy-single-account-k8s-aws.json)" 70 | default = true 71 | } 72 | -------------------------------------------------------------------------------- /modules/infrastructure/ssm/README.md: -------------------------------------------------------------------------------- 1 | # AWS System Manager 2 | 3 | 4 | Sysdig Secure for Cloud uses [ssm](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html)`aws_ssm_parameter` in order to store the `sysdig_secure_api_token` parameter in its "Parameter Store" 5 | and pass it, in a safe way, to all the modules that require it. 6 | 7 | 8 | ## Requirements 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 13 | | [aws](#requirement\_aws) | >= 3.50.0 | 14 | 15 | ## Providers 16 | 17 | | Name | Version | 18 | |------|---------| 19 | | [aws](#provider\_aws) | >= 3.50.0 | 20 | 21 | ## Modules 22 | 23 | No modules. 24 | 25 | ## Resources 26 | 27 | | Name | Type | 28 | |------|------| 29 | | [aws_ssm_parameter.secure_api_token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | 30 | 31 | ## Inputs 32 | 33 | | Name | Description | Type | Default | Required | 34 | |------|-------------|------|---------|:--------:| 35 | | [sysdig\_secure\_api\_token](#input\_sysdig\_secure\_api\_token) | Sysdig Secure API token | `string` | n/a | yes | 36 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 37 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 38 | 39 | ## Outputs 40 | 41 | | Name | Description | 42 | |------|-------------| 43 | | [secure\_api\_token\_secret\_arn](#output\_secure\_api\_token\_secret\_arn) | ARN of Sysdig Secure API Token secret | 44 | | [secure\_api\_token\_secret\_name](#output\_secure\_api\_token\_secret\_name) | Name of Sysdig Secure API Token secret | 45 | 46 | 47 | ## Authors 48 | 49 | Module is maintained and supported by [Sysdig](https://sysdig.com). 50 | 51 | ## License 52 | 53 | Apache 2 Licensed. See LICENSE for full details. 54 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/cloudconnector-config.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | default_config = yamlencode(merge({ 3 | logging = "info" 4 | rules = [] 5 | ingestors = [ 6 | merge( 7 | local.deploy_sqs ? { 8 | cloudtrail-sns-sqs = merge( 9 | { 10 | queueURL = module.cloud_connector_sqs[0].cloudtrail_sns_subscribed_sqs_url 11 | }, 12 | var.is_organizational ? { 13 | assumeRole = var.organizational_config.sysdig_secure_for_cloud_role_arn 14 | } : {} 15 | ) 16 | } : {}, 17 | !local.deploy_sqs && var.existing_cloudtrail_config.cloudtrail_s3_sns_sqs_url != null ? { 18 | aws-cloudtrail-s3-sns-sqs = merge( 19 | { 20 | queueURL = var.existing_cloudtrail_config.cloudtrail_s3_sns_sqs_url 21 | }, 22 | var.is_organizational ? { 23 | assumeRole = var.organizational_config.sysdig_secure_for_cloud_role_arn 24 | } : {} 25 | ) 26 | } : {}) 27 | ] 28 | }, 29 | { 30 | scanners = local.deploy_image_scanning ? [ 31 | merge(var.deploy_beta_image_scanning_ecr ? { 32 | aws-ecr-inline = merge({}, 33 | var.is_organizational ? { 34 | masterOrganizationRole = var.organizational_config.sysdig_secure_for_cloud_role_arn 35 | organizationalRolePerAccount = var.organizational_config.organizational_role_per_account 36 | } : {}) 37 | } : {}, 38 | var.deploy_image_scanning_ecr ? { 39 | aws-ecr = merge({ 40 | codeBuildProject = var.build_project_name 41 | secureAPITokenSecretName = var.secure_api_token_secret_name 42 | }, 43 | var.is_organizational ? { 44 | masterOrganizationRole = var.organizational_config.sysdig_secure_for_cloud_role_arn 45 | organizationalRolePerAccount = var.organizational_config.organizational_role_per_account 46 | } : {}) 47 | } : {}, 48 | var.deploy_image_scanning_ecs ? { 49 | aws-ecs = merge({ 50 | codeBuildProject = var.build_project_name 51 | secureAPITokenSecretName = var.secure_api_token_secret_name 52 | }, 53 | var.is_organizational ? { 54 | masterOrganizationRole = var.organizational_config.sysdig_secure_for_cloud_role_arn 55 | organizationalRolePerAccount = var.organizational_config.organizational_role_per_account 56 | } : {}) 57 | } : {}) 58 | ] : [] 59 | } 60 | )) 61 | } 62 | -------------------------------------------------------------------------------- /examples/single-account-ecs/main.tf: -------------------------------------------------------------------------------- 1 | #------------------------------------- 2 | # general resources 3 | #------------------------------------- 4 | module "resource_group" { 5 | source = "../../modules/infrastructure/resource-group" 6 | 7 | name = var.name 8 | tags = var.tags 9 | } 10 | 11 | module "ssm" { 12 | source = "../../modules/infrastructure/ssm" 13 | name = var.name 14 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 15 | tags = var.tags 16 | } 17 | 18 | 19 | # 20 | # scanning 21 | # 22 | 23 | module "codebuild" { 24 | count = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs ? 1 : 0 25 | 26 | source = "../../modules/infrastructure/codebuild" 27 | name = "${var.name}-codebuild" 28 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 29 | 30 | tags = var.tags 31 | # note. this is required to avoid racing conditions 32 | depends_on = [module.ssm] 33 | } 34 | 35 | 36 | # 37 | # threat-detection 38 | # 39 | 40 | module "cloud_connector" { 41 | source = "../../modules/services/cloud-connector-ecs" 42 | name = "${var.name}-cloudconnector" 43 | 44 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 45 | 46 | deploy_beta_image_scanning_ecr = var.deploy_beta_image_scanning_ecr 47 | deploy_image_scanning_ecr = var.deploy_image_scanning_ecr 48 | deploy_image_scanning_ecs = var.deploy_image_scanning_ecs 49 | 50 | is_organizational = false 51 | 52 | build_project_arn = length(module.codebuild) == 1 ? module.codebuild[0].project_arn : "na" 53 | build_project_name = length(module.codebuild) == 1 ? module.codebuild[0].project_name : "na" 54 | 55 | existing_cloudtrail_config = { 56 | cloudtrail_sns_arn = local.cloudtrail_sns_arn 57 | } 58 | 59 | 60 | ecs_cluster_name = local.ecs_cluster_name 61 | ecs_vpc_id = local.ecs_vpc_id 62 | ecs_vpc_subnets_private_ids = local.ecs_vpc_subnets_private_ids 63 | ecs_task_cpu = var.ecs_task_cpu 64 | ecs_task_memory = var.ecs_task_memory 65 | image = var.cloud_connector_image 66 | 67 | tags = var.tags 68 | depends_on = [local.cloudtrail_sns_arn, module.ssm] 69 | 70 | enable_autoscaling = var.enable_autoscaling 71 | autoscaling_config = { 72 | min_replicas = var.autoscaling_config.min_replicas 73 | max_replicas = var.autoscaling_config.max_replicas 74 | upscale_threshold = var.autoscaling_config.upscale_threshold 75 | downscale_threshold = var.autoscaling_config.downscale_threshold 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/trigger-events/README.md: -------------------------------------------------------------------------------- 1 | # Sysdig Secure for Cloud in AWS
[ Example :: Trigger-Events] 2 | 3 | This example helps to trigger AWS Events. Cloud Connector stack is required to be able to generate events. 4 | After applying this module, a new AWS IAM Policy will be created. **Create IAM Policy that Allows All** event will prompt once the module is applied. 5 | 6 | ## Prerequisites 7 | 8 | Minimum requirements: 9 | 10 | 1. Deploy Cloud Connector Stack on AWS. 11 | 2. Configure [Terraform **AWS** Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) 12 | 13 | ## Notice 14 | 15 | * **Resource creation inventory** Find all the resources created by Sysdig examples in the resource-group `sysdig-secure-for-cloud` (AWS Resource Group & Tag Editor)

16 | * **Deployment cost** This example will create resources that cost money.
Run `terraform destroy` when you don't need them anymore 17 | 18 | 19 | ## Usage 20 | 21 | For quick testing, use this snippet on your terraform files 22 | 23 | ```terraform 24 | provider "aws" { 25 | region = "; ex. us-east-1" 26 | } 27 | 28 | module "secure_for_cloud_aws_trigger-events"{ 29 | source = "sysdiglabs/secure-for-cloud/aws//test/trigger-events" 30 | } 31 | ``` 32 | 33 | To run this example you need have your [aws account profile configured in CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) and to execute: 34 | ```terraform 35 | $ terraform init 36 | $ terraform plan 37 | $ terraform apply 38 | ``` 39 | 40 | 41 | ## Requirements 42 | 43 | | Name | Version | 44 | |------|---------| 45 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 46 | | [aws](#requirement\_aws) | >= 4.0.0 | 47 | 48 | ## Providers 49 | 50 | | Name | Version | 51 | |------|---------| 52 | | [aws](#provider\_aws) | >= 4.0.0 | 53 | 54 | ## Modules 55 | 56 | No modules. 57 | 58 | ## Resources 59 | 60 | | Name | Type | 61 | |------|------| 62 | | [aws_iam_policy.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | 63 | | [aws_iam_policy_document.flow_log_cloudwatch_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 64 | 65 | ## Inputs 66 | 67 | No inputs. 68 | 69 | ## Outputs 70 | 71 | No outputs. 72 | 73 | 74 | 75 | ## Authors 76 | 77 | Module is maintained and supported by [Sysdig](https://sysdig.com). 78 | 79 | ## License 80 | 81 | Apache 2 Licensed. See LICENSE for full details. 82 | -------------------------------------------------------------------------------- /modules/infrastructure/sqs-sns-subscription/README.md: -------------------------------------------------------------------------------- 1 | # Create an SQS and subscribe to SNS 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 9 | | [aws](#requirement\_aws) | >= 3.50.0 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 3.50.0 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_sns_topic_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | 26 | | [aws_sqs_queue.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | 27 | | [aws_sqs_queue_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | 28 | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 29 | 30 | ## Inputs 31 | 32 | | Name | Description | Type | Default | Required | 33 | |------|-------------|------|---------|:--------:| 34 | | [cloudtrail\_sns\_arn](#input\_cloudtrail\_sns\_arn) | CloudTrail SNS Topic ARN to subscribe the SQS queue | `string` | n/a | yes | 35 | | [name](#input\_name) | Queue name | `string` | n/a | yes | 36 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 37 | 38 | ## Outputs 39 | 40 | | Name | Description | 41 | |------|-------------| 42 | | [cloudtrail\_sns\_subscribed\_sqs\_arn](#output\_cloudtrail\_sns\_subscribed\_sqs\_arn) | ARN of the cloudtrail-sns subscribed sqs | 43 | | [cloudtrail\_sns\_subscribed\_sqs\_url](#output\_cloudtrail\_sns\_subscribed\_sqs\_url) | URL of the cloudtrail-sns subscribed sqs | 44 | 45 | 46 | ## Authors 47 | 48 | Module is maintained and supported by [Sysdig](https://sysdig.com). 49 | 50 | ## License 51 | 52 | Apache 2 Licensed. See LICENSE for full details. 53 | -------------------------------------------------------------------------------- /examples-internal/organizational-k8s-threat-reuse_cloudtrail_s3/diagram.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Cluster, Diagram, Edge, Node 3 | from diagrams.aws.compute import EKS 4 | from diagrams.aws.general import General 5 | from diagrams.aws.integration import SNS, SQS 6 | from diagrams.aws.management import Cloudtrail 7 | from diagrams.aws.security import IAM, IAMRole 8 | from diagrams.aws.storage import S3 9 | from diagrams.custom import Custom 10 | 11 | from diagrams.k8s.group import Namespace 12 | from diagrams.k8s.compute import Deployment 13 | 14 | diagram_attr = { 15 | "pad":"0.25" 16 | } 17 | 18 | role_attr = { 19 | "imagescale":"false", 20 | "height":"1.5", 21 | "width":"3", 22 | "fontsize":"9", 23 | } 24 | 25 | color_event="firebrick" 26 | color_scanning = "dark-green" 27 | color_permission="red" 28 | color_creates="darkblue" 29 | color_non_important="gray" 30 | color_sysdig="lightblue" 31 | 32 | 33 | 34 | with Diagram("Sysdig Secure for Cloud{}(org-threat_detection-k8s-cloudtrail_s3_sns_sqs-eks)".format("\n"), graph_attr=diagram_attr, filename="diagram", show=True, direction="TB"): 35 | 36 | with Cluster("AWS account (sysdig)"): 37 | sds = Custom("Sysdig Secure", "../../resources/diag-sysdig-icon.png") 38 | 39 | with Cluster("AWS organization"): 40 | 41 | with Cluster("member account", graph_attr={"bgcolor":"lightblue"}): 42 | # resources = General("resources-1..n\n(events)") 43 | 44 | with Cluster("sysdig-secure-for-cloud resources"): 45 | eks = EKS("EKS\n(pre-existing)") 46 | with Cluster("namespace: sfc"): 47 | cc_deployment = Deployment("cloud-connector") 48 | eks_deployments = [cc_deployment] 49 | 50 | 51 | with Cluster("management account"): 52 | # resources2 = General("resources-1..n\n(events)") 53 | 54 | cloudtrail = Cloudtrail("cloudtrail\n(organizational)", shape="plaintext") 55 | cloudtrail_s3 = S3("cloudtrail-s3-events") 56 | sns = [SNS("sns /path-1"), SNS("sns /path-2"), SNS("sns /path-n")] 57 | sqs = SQS("sqs") 58 | cloudtrail >> Edge(color=color_event) >> cloudtrail_s3 >> Edge(color=color_event) >> sns << sqs 59 | # resources2 >> Edge(color=color_event, style="dashed") >> cloudtrail 60 | 61 | management_credentials = IAM("credentials", fontsize="10") 62 | 63 | cc_deployment >> Edge(color=color_event, style="dashed", label="subscribed") >> sqs 64 | # resources >> Edge(color=color_event, style="dashed") >> cloudtrail 65 | 66 | cc_deployment >> Edge(color=color_sysdig) >> sds 67 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/variables.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------- 2 | # optionals - with defaults 3 | #--------------------------------- 4 | 5 | # 6 | # module composition 7 | # 8 | 9 | variable "is_organizational" { 10 | type = bool 11 | default = false 12 | description = "true/false whether cloudtrail is organizational or not" 13 | } 14 | 15 | 16 | variable "organizational_config" { 17 | type = object({ 18 | sysdig_secure_for_cloud_member_account_id = string 19 | organizational_role_per_account = string 20 | }) 21 | default = { 22 | sysdig_secure_for_cloud_member_account_id = null 23 | organizational_role_per_account = null 24 | } 25 | description = <<-EOT 26 | organizational_config. following attributes must be given 27 |
  • `sysdig_secure_for_cloud_member_account_id` to enable reading permission
  • 28 |
  • `organizational_role_per_account` to enable SNS topic subscription. by default "OrganizationAccountAccessRole"
29 | EOT 30 | } 31 | 32 | # 33 | # module config 34 | # 35 | 36 | variable "s3_bucket_expiration_days" { 37 | type = number 38 | default = 5 39 | description = "Number of days that the logs will persist in the bucket" 40 | } 41 | 42 | variable "temporary_s3_bucket_public_block" { 43 | type = bool 44 | default = true 45 | description = "Create a S3 bucket public access block configuration
This is a temporary variable that will be removed once https://aws.amazon.com/blogs/aws/heads-up-amazon-s3-security-changes-are-coming-in-april-of-2023/ is made effective.
After it, the resource will never be created." 46 | } 47 | 48 | variable "cloudtrail_kms_enable" { 49 | type = bool 50 | default = true 51 | description = "true/false whether s3 should be encrypted" 52 | } 53 | 54 | variable "is_multi_region_trail" { 55 | type = bool 56 | default = true 57 | description = "true/false whether cloudtrail will ingest multiregional events" 58 | } 59 | 60 | 61 | # 62 | # general 63 | # 64 | 65 | variable "name" { 66 | type = string 67 | default = "sfc" 68 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 69 | } 70 | 71 | variable "tags" { 72 | type = map(string) 73 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 74 | default = { 75 | "product" = "sysdig-secure-for-cloud" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /modules/infrastructure/ecs-vpc/README.md: -------------------------------------------------------------------------------- 1 | # ECS Cluster / VPC / SecGroup 2 | 3 | 4 | 5 | ## Requirements 6 | 7 | | Name | Version | 8 | |------|---------| 9 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 10 | | [aws](#requirement\_aws) | >= 3.50.0 | 11 | 12 | ## Providers 13 | 14 | | Name | Version | 15 | |------|---------| 16 | | [aws](#provider\_aws) | >= 3.50.0 | 17 | 18 | ## Modules 19 | 20 | | Name | Source | Version | 21 | |------|--------|---------| 22 | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | >=3.14.0 | 23 | 24 | ## Resources 25 | 26 | | Name | Type | 27 | |------|------| 28 | | [aws_ecs_cluster.ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | 29 | | [aws_availability_zones.zones](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | 30 | 31 | ## Inputs 32 | 33 | | Name | Description | Type | Default | Required | 34 | |------|-------------|------|---------|:--------:| 35 | | [ecs\_vpc\_region\_azs](#input\_ecs\_vpc\_region\_azs) | List of Availability Zones for ECS VPC creation. e.g.: ["apne1-az1", "apne1-az2"]. If defaulted, two of the default 'aws\_availability\_zones' datasource will be taken | `list(string)` | `[]` | no | 36 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 37 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 38 | 39 | ## Outputs 40 | 41 | | Name | Description | 42 | |------|-------------| 43 | | [ecs\_cluster\_name](#output\_ecs\_cluster\_name) | ID of the ECS cluster | 44 | | [ecs\_vpc\_id](#output\_ecs\_vpc\_id) | ID of the VPC for the ECS cluster | 45 | | [ecs\_vpc\_subnets\_private\_ids](#output\_ecs\_vpc\_subnets\_private\_ids) | IDs of the private subnets of the VPC for the ECS cluster | 46 | 47 | 48 | ## Authors 49 | 50 | Module is maintained and supported by [Sysdig](https://sysdig.com). 51 | 52 | ## License 53 | 54 | Apache 2 Licensed. See LICENSE for full details. 55 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/ecs-service.tf: -------------------------------------------------------------------------------- 1 | data "aws_ecs_cluster" "this" { 2 | cluster_name = var.ecs_cluster_name 3 | } 4 | 5 | resource "aws_ecs_service" "service" { 6 | name = var.name 7 | 8 | cluster = data.aws_ecs_cluster.this.id 9 | network_configuration { 10 | subnets = var.ecs_vpc_subnets_private_ids 11 | security_groups = [aws_security_group.sg.id] 12 | } 13 | 14 | desired_count = 1 15 | launch_type = "FARGATE" 16 | task_definition = aws_ecs_task_definition.task_definition.arn 17 | wait_for_steady_state = true 18 | tags = var.tags 19 | 20 | lifecycle { 21 | ignore_changes = [desired_count] 22 | } 23 | } 24 | 25 | 26 | resource "aws_ecs_task_definition" "task_definition" { 27 | family = var.name 28 | requires_compatibilities = ["FARGATE"] 29 | network_mode = "awsvpc" 30 | execution_role_arn = aws_iam_role.execution.arn 31 | # ARN of the task execution role that the Amazon ECS container agent and the Docker daemon can assume 32 | task_role_arn = local.ecs_task_role_arn 33 | # ARN of IAM role that allows your Amazon ECS container task to make calls to other AWS services. 34 | cpu = var.ecs_task_cpu 35 | memory = var.ecs_task_memory 36 | 37 | container_definitions = jsonencode([ 38 | { 39 | environment = local.task_env_vars 40 | name = "CloudConnector" 41 | image = var.image 42 | essential = true 43 | secrets = [ 44 | { 45 | name = "SECURE_API_TOKEN" 46 | valueFrom = var.secure_api_token_secret_name 47 | } 48 | ] 49 | portMappings = [ 50 | { 51 | containerPort = 5000 52 | } 53 | ] 54 | logConfiguration = { 55 | logDriver = "awslogs" 56 | options = { 57 | awslogs-group = aws_cloudwatch_log_group.log.id 58 | awslogs-region = data.aws_region.current.name 59 | awslogs-stream-prefix = "ecs" 60 | } 61 | } 62 | }, 63 | ]) 64 | tags = var.tags 65 | } 66 | 67 | 68 | locals { 69 | suffix_org = var.is_organizational ? "org" : "single" 70 | task_env_vars = concat([ 71 | { 72 | name = "VERIFY_SSL" 73 | value = tostring(local.verify_ssl) 74 | }, 75 | { 76 | name = "TELEMETRY_DEPLOYMENT_METHOD" 77 | value = "terraform_aws_ecs_${local.suffix_org}" 78 | }, 79 | { 80 | name = "CONFIG" 81 | value = base64encode(local.default_config) 82 | }, 83 | { 84 | name = "SECURE_URL", 85 | value = data.sysdig_secure_connection.current.secure_url 86 | } 87 | ], flatten([ 88 | for env_key, env_value in var.extra_env_vars : [ 89 | { 90 | name = env_key, 91 | value = env_value 92 | } 93 | ] 94 | ]) 95 | ) 96 | } 97 | -------------------------------------------------------------------------------- /test/eks/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "eks_cluster" { 2 | name = "${var.name}-eks_cluster" 3 | 4 | assume_role_policy = < Being able to allow/deny member accounts where Secure for Cloud is deployed is under development. 8 | 9 | ### Features 10 | 11 | This use case provides the following [Sysdig Secure For Cloud](https://docs.sysdig.com/en/docs/sysdig-secure/sysdig-secure-for-cloud/#features) features: 12 | 13 | - [Threat Detection](https://docs.sysdig.com/en/docs/sysdig-secure/policies/threat-detect-policies/) 14 | 15 | ## Preparation 16 | 17 | ### AWS Terraform Providers 18 | 19 | You will work on the following setups: default and member terraform providers. 20 | 21 | 1. Member account: Use the [default use-case snippet](#terraform-snippet) to deploy compute and compliance role in a member account. 22 | 2. Management account: Use the [default use-case snippet](#terraform-snippet) to deploy compute on the Management account. 23 | 24 | ```terraform 25 | provider "aws" { 26 | region = var.region 27 | } 28 | 29 | 30 | module "secure_for_cloud_organizational" { 31 | providers = { 32 | aws.member = aws 33 | } 34 | ... 35 | } 36 | ``` 37 | 38 | ## Terraform Snippet 39 | 40 | ```terraform 41 | terraform { 42 | required_providers { 43 | sysdig = { 44 | source = "sysdiglabs/sysdig" 45 | configuration_aliases = [aws.member] 46 | } 47 | } 48 | } 49 | 50 | provider "sysdig" { 51 | sysdig_secure_url = "" 52 | sysdig_secure_api_token = "" 53 | } 54 | 55 | # provider used to deploy RO compliance role on organizational accounts 56 | provider "aws" { 57 | region = "" # must match s3 AND sqs region 58 | } 59 | 60 | # provider used to deploy sfc on the selected member-account 61 | provider "aws" { 62 | alias = "member" 63 | region = "" # must match s3 AND sqs region 64 | assume_role { 65 | # ORG_MEMBER_SFC_ACCOUNT_ID is the organizational account where sysdig secure for cloud compute component is to be deployed 66 | # 'OrganizationAccountAccessRole' is the default role created by AWS for management-account users to be able to admin member accounts. 67 | # if this is changed, please change to the `examples/organizational` input var `organizational_member_default_admin_role` too 68 | #
https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access.html 69 | role_arn = "arn:aws:iam:::role/OrganizationAccountAccessRole" 70 | } 71 | 72 | module "secure_for_cloud_organizational" { 73 | providers = { 74 | aws.member = aws.member 75 | } 76 | source = "sysdiglabs/secure-for-cloud/aws//examples/organizational" 77 | 78 | sysdig_secure_for_cloud_member_account_id = "" 79 | ... 80 | } 81 | ``` 82 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-ecs/main.tf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------ 2 | # management account role 3 | # ------------------------------------------ 4 | resource "aws_iam_role" "secure_for_cloud_role" { 5 | name = "${var.name}-SysdigSecureForCloudRole" 6 | assume_role_policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_trusted.json 7 | tags = var.tags 8 | } 9 | 10 | # enable cloudtrail_s3 RO access 11 | resource "aws_iam_role_policy" "sysdig_secure_for_cloud_role_s3" { 12 | name = "${var.name}-AllowCloudtrailS3Policy" 13 | role = aws_iam_role.secure_for_cloud_role.id 14 | policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_s3.json 15 | } 16 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_s3" { 17 | statement { 18 | effect = "Allow" 19 | actions = [ 20 | "s3:ListBucket", 21 | "s3:GetObject" 22 | ] 23 | resources = [ 24 | var.cloudtrail_s3_arn, 25 | "${var.cloudtrail_s3_arn}/*" 26 | ] 27 | } 28 | } 29 | 30 | 31 | # enable image-scanning on member-account repositories 32 | resource "aws_iam_role_policy" "sysdig_secure_for_cloud_role_assume_role" { 33 | name = "${var.name}-AllowAssumeRoleInChildAccounts" 34 | role = aws_iam_role.secure_for_cloud_role.id 35 | policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_assume_role.json 36 | } 37 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_assume_role" { 38 | statement { 39 | effect = "Allow" 40 | actions = [ 41 | "sts:AssumeRole", 42 | ] 43 | resources = [ 44 | "arn:aws:iam::*:role/${var.organizational_role_per_account}" 45 | ] 46 | } 47 | } 48 | 49 | 50 | # --------------------------------------------- 51 | # enable cloud-connector module ECS Task role to AssumeRole on this secure_for_cloud_role 52 | # required for cloudtrail_sns/s3 resource read/subscribe access 53 | # --------------------------------------------- 54 | 55 | # trust ecs-task-role identifier to assumeRole 56 | data "aws_iam_role" "ecs_task_role" { 57 | provider = aws.member 58 | name = var.cloudconnector_ecs_task_role_name 59 | } 60 | 61 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_trusted" { 62 | statement { 63 | effect = "Allow" 64 | principals { 65 | type = "AWS" 66 | identifiers = [ 67 | data.aws_iam_role.ecs_task_role.arn 68 | ] 69 | } 70 | actions = ["sts:AssumeRole"] 71 | } 72 | } 73 | 74 | # enable ecs-task resource to assumeRole 75 | resource "aws_iam_role_policy" "enable_assume_secure_for_cloud_role" { 76 | provider = aws.member 77 | name = "${var.name}-EnableSysdigSecureForCloudRole" 78 | 79 | role = var.cloudconnector_ecs_task_role_name 80 | policy = data.aws_iam_policy_document.enable_assume_secure_for_cloud_role.json 81 | } 82 | data "aws_iam_policy_document" "enable_assume_secure_for_cloud_role" { 83 | statement { 84 | effect = "Allow" 85 | actions = [ 86 | "sts:AssumeRole" 87 | ] 88 | resources = [aws_iam_role.secure_for_cloud_role.arn] 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /examples/single-account-k8s/cloud-connector.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | deploy_image_scanning = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs || var.deploy_beta_image_scanning_ecr 3 | } 4 | 5 | #------------------------------------- 6 | # requirements 7 | #------------------------------------- 8 | module "cloud_connector_sqs" { 9 | source = "../../modules/infrastructure/sqs-sns-subscription" 10 | 11 | name = var.name 12 | cloudtrail_sns_arn = local.cloudtrail_sns_arn 13 | tags = var.tags 14 | } 15 | 16 | module "codebuild" { 17 | count = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs ? 1 : 0 18 | source = "../../modules/infrastructure/codebuild" 19 | 20 | name = var.name 21 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 22 | 23 | tags = var.tags 24 | # note. this is required to avoid race conditions 25 | depends_on = [module.ssm] 26 | } 27 | 28 | #------------------------------------- 29 | # cloud_connector 30 | #------------------------------------- 31 | resource "helm_release" "cloud_connector" { 32 | name = "cloud-connector" 33 | repository = "https://charts.sysdig.com" 34 | chart = "cloud-connector" 35 | 36 | create_namespace = true 37 | namespace = var.name 38 | 39 | set { 40 | name = "sysdig.url" 41 | value = data.sysdig_secure_connection.current.secure_url 42 | } 43 | 44 | set_sensitive { 45 | name = "sysdig.secureAPIToken" 46 | value = data.sysdig_secure_connection.current.secure_api_token 47 | } 48 | 49 | dynamic "set_sensitive" { 50 | for_each = var.deploy_aws_iam_user ? [true] : [] 51 | content { 52 | name = "aws.accessKeyId" 53 | value = module.iam_user[0].sfc_user_access_key_id 54 | } 55 | } 56 | 57 | dynamic "set_sensitive" { 58 | for_each = var.deploy_aws_iam_user ? [true] : [] 59 | content { 60 | name = "aws.secretAccessKey" 61 | value = module.iam_user[0].sfc_user_secret_access_key 62 | } 63 | } 64 | 65 | set { 66 | name = "aws.region" 67 | value = data.aws_region.current.name 68 | } 69 | 70 | set { 71 | name = "telemetryDeploymentMethod" 72 | value = "terraform_aws_k8s_single" 73 | } 74 | 75 | values = [ 76 | yamlencode({ 77 | ingestors = [ 78 | { 79 | cloudtrail-sns-sqs = { 80 | queueURL = module.cloud_connector_sqs.cloudtrail_sns_subscribed_sqs_url 81 | } 82 | } 83 | ] 84 | scanners = local.deploy_image_scanning ? [ 85 | merge( 86 | var.deploy_beta_image_scanning_ecr ? { 87 | aws-ecr-inline = {} 88 | } : {}, 89 | var.deploy_image_scanning_ecr ? { 90 | aws-ecr = { 91 | codeBuildProject = module.codebuild[0].project_name 92 | secureAPITokenSecretName = module.ssm.secure_api_token_secret_name 93 | } 94 | } : {}, 95 | var.deploy_image_scanning_ecs ? { 96 | aws-ecs = { 97 | codeBuildProject = module.codebuild[0].project_name 98 | secureAPITokenSecretName = module.ssm.secure_api_token_secret_name 99 | } 100 | } : {}) 101 | ] : [] 102 | }) 103 | ] 104 | depends_on = [module.iam_user[0]] 105 | } 106 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | #--------------------------------- 4 | # optionals - with defaults 5 | #--------------------------------- 6 | 7 | 8 | # 9 | # cloudtrail configuration 10 | # 11 | variable "cloudtrail_sns_arn" { 12 | type = string 13 | default = "create" 14 | description = "ARN of a cloudtrail-sns topic" 15 | } 16 | 17 | # 18 | # scanning configuration 19 | # 20 | 21 | variable "deploy_beta_image_scanning_ecr" { 22 | type = bool 23 | description = "true/false whether to deploy the beta image scanning on ECR pushed images (experimental and unsupported)" 24 | default = false 25 | } 26 | 27 | variable "deploy_image_scanning_ecr" { 28 | type = bool 29 | description = "true/false whether to deploy the image scanning on ECR pushed images" 30 | default = false 31 | } 32 | 33 | variable "deploy_image_scanning_ecs" { 34 | type = bool 35 | description = "true/false whether to deploy the image scanning on ECS running images" 36 | default = false 37 | } 38 | 39 | # 40 | # general 41 | # 42 | 43 | variable "name" { 44 | type = string 45 | description = "Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances" 46 | default = "sfc" 47 | } 48 | 49 | variable "tags" { 50 | type = map(string) 51 | description = "customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags)" 52 | default = { 53 | "product" = "sysdig-secure-for-cloud" 54 | } 55 | } 56 | 57 | variable "sysdig_secure_api_token" { 58 | type = string 59 | sensitive = true 60 | description = "Sysdig secure api token" 61 | } 62 | 63 | variable "sysdig_secure_url" { 64 | type = string 65 | description = "Sysdig secure endpoint" 66 | default = "https://secure.sysdig.com" 67 | } 68 | 69 | ######## 70 | variable "cloudwatch_log_retention" { 71 | type = number 72 | default = 5 73 | description = "Days to keep logs for CloudConnector" 74 | } 75 | 76 | variable "build_project_arn" { 77 | type = string 78 | description = "Code Build project arn" 79 | } 80 | 81 | variable "build_project_name" { 82 | type = string 83 | description = "Code Build project name" 84 | } 85 | 86 | variable "secure_api_token_secret_name" { 87 | type = string 88 | description = "Secure API token secret name" 89 | default = "" 90 | } 91 | 92 | variable "verify_ssl" { 93 | type = bool 94 | default = true 95 | description = "true/false to determine ssl verification for sysdig_secure_url" 96 | } 97 | 98 | 99 | variable "cloudconnector_ecr_image_uri" { 100 | type = string 101 | description = "URI to image on ECR" 102 | default = "public.ecr.aws/o5x4u2t4/cloud-connector:latest" 103 | } 104 | 105 | variable "secure_api_token_secret_arn" { 106 | type = string 107 | description = "ARN of Sysdig Secure API token SSM parameter" 108 | } 109 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # requirements 3 | # - install pre-commit (latest) 4 | # - install terraform-docs (latest) 5 | # - see .github/workflows/ci-pull-request.yaml for more info on what's being valiated on CI 6 | # $ pre-commit run --color=always --show-diff-on-failure --all-files 7 | # 8 | 9 | 10 | repos: 11 | # create a custom terraform validate for the examples, as launching the validation in the root dir won't work and give 12 | # "Error: Provider configuration not present" error 13 | # https://github.com/hashicorp/terraform/issues/21416 14 | # https://discuss.hashicorp.com/t/how-to-run-terraform-validate-on-a-module-that-is-supplied-the-providers-via-an-alias/34664/2 15 | # - repo: local 16 | # hooks: 17 | # - id: terraform_validate 18 | # name: Terraform validate 19 | # entry: resources/scripts/terraform_validate.sh 20 | # pass_filenames: false 21 | # language: script 22 | # verbose: true 23 | 24 | # https://github.com/antonbabenko/pre-commit-terraform/blob/master/README.md#terraform_validate (point 4) 25 | - repo: local 26 | hooks: 27 | - id: terraform_clean 28 | name: "Terraform Cleanup" 29 | pass_filenames: false 30 | language: system 31 | entry: bash -c "find . \( -iname ".terraform*" ! -iname ".terraform-docs*" ! -path "*/test/*" \) -print0 | xargs -0 rm -r; true" 32 | 33 | 34 | - repo: local 35 | # Adding this patch to fix organizational multi-provider terraform validate error 36 | # 'missing provider provider["registry.terraform.io/hashicorp/aws"].member' 37 | # https://github.com/antonbabenko/pre-commit-terraform/#terraform_validate 38 | hooks: 39 | - id: generate_tf_providers 40 | name: generate_tf_providers 41 | language: system 42 | entry: bash -c "./resources/scripts/generate_providers.sh ./modules/infrastructure/permissions/org-role-ecs ./examples/organizational" 43 | pass_filenames: false 44 | 45 | - repo: https://github.com/antonbabenko/pre-commit-terraform 46 | rev: v1.64.0 47 | hooks: 48 | - id: terraform_fmt 49 | - id: terraform_docs 50 | args: 51 | - '--args=--sort-by required' 52 | - id: terraform_tflint 53 | exclude: (test)|(examples-internal)\/.*$ 54 | args: 55 | - '--args=--only=terraform_comment_syntax' 56 | - '--args=--only=terraform_deprecated_index' 57 | - '--args=--only=terraform_deprecated_interpolation' 58 | - '--args=--only=terraform_documented_outputs' 59 | - '--args=--only=terraform_documented_variables' 60 | - '--args=--only=terraform_module_pinned_source' 61 | - '--args=--only=terraform_module_version' 62 | - '--args=--only=terraform_naming_convention' 63 | - '--args=--only=terraform_required_providers' 64 | - '--args=--only=terraform_required_version' 65 | - '--args=--only=terraform_standard_module_structure' 66 | - '--args=--only=terraform_typed_variables' 67 | - '--args=--only=terraform_unused_declarations' 68 | - '--args=--only=terraform_unused_required_providers' 69 | - '--args=--only=terraform_workspace_remote' 70 | # https://github.com/antonbabenko/pre-commit-terraform#terraform_validate 71 | - id: terraform_validate 72 | exclude: (test)|(examples-internal)\/.*$ 73 | - id: terrascan 74 | exclude: (test) 75 | args: 76 | - '--args=--skip-rules AC_AWS_0369' 77 | - repo: https://github.com/pre-commit/pre-commit-hooks 78 | rev: v4.1.0 79 | hooks: 80 | - id: check-merge-conflict 81 | - id: end-of-file-fixer 82 | - id: trailing-whitespace 83 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-apprunner/apprunner.tf: -------------------------------------------------------------------------------- 1 | resource "aws_apprunner_service" "cloudconnector" { 2 | service_name = var.name 3 | 4 | source_configuration { 5 | image_repository { 6 | image_configuration { 7 | port = "5000" 8 | runtime_environment_variables = { 9 | CONFIG = base64encode(local.default_config) 10 | SECURE_API_TOKEN = var.sysdig_secure_api_token 11 | SECURE_URL = var.sysdig_secure_url 12 | VERIFY_SSL = local.verify_ssl 13 | TELEMETRY_DEPLOYMENT_METHOD = "terraform_aws_apprunner_single" 14 | } 15 | } 16 | image_identifier = var.cloudconnector_ecr_image_uri 17 | image_repository_type = "ECR_PUBLIC" 18 | } 19 | auto_deployments_enabled = false 20 | } 21 | 22 | instance_configuration { 23 | instance_role_arn = aws_iam_role.secure_for_cloud_role.arn 24 | } 25 | 26 | tags = var.tags 27 | } 28 | 29 | resource "aws_iam_role" "secure_for_cloud_role" { 30 | name = "${var.name}-SecureForCloudRole" 31 | assume_role_policy = data.aws_iam_policy_document.sysdig_secure_for_cloud_role_trusted.json 32 | tags = var.tags 33 | } 34 | 35 | resource "aws_iam_role_policy" "secure_for_cloud_role" { 36 | name = "${var.name}-SecureForCloudRolePolicy" 37 | role = aws_iam_role.secure_for_cloud_role.id 38 | policy = data.aws_iam_policy_document.cloud_connector.json 39 | } 40 | 41 | data "aws_iam_policy_document" "sysdig_secure_for_cloud_role_trusted" { 42 | statement { 43 | effect = "Allow" 44 | principals { 45 | type = "Service" 46 | identifiers = ["tasks.apprunner.amazonaws.com"] 47 | } 48 | actions = ["sts:AssumeRole"] 49 | } 50 | } 51 | 52 | data "aws_iam_policy_document" "cloud_connector" { 53 | statement { 54 | sid = "AllowS3" 55 | effect = "Allow" 56 | actions = [ 57 | "s3:ListBucket", 58 | "s3:GetObject" 59 | ] 60 | resources = ["*"] 61 | } 62 | statement { 63 | sid = "AllowSQS" 64 | effect = "Allow" 65 | actions = [ 66 | "sqs:GetQueueUrl", 67 | "sqs:ListQueues", 68 | "sqs:ReceiveMessage", 69 | "sqs:DeleteMessage" 70 | ] 71 | resources = ["*"] 72 | } 73 | 74 | statement { 75 | sid = "AllowSSM" 76 | effect = "Allow" 77 | actions = [ 78 | "ssm:GetParameters" 79 | ] 80 | resources = [var.secure_api_token_secret_arn] 81 | } 82 | 83 | dynamic "statement" { 84 | for_each = var.deploy_image_scanning_ecr || var.deploy_beta_image_scanning_ecr ? [1] : [] 85 | content { 86 | sid = "AllowECR" 87 | effect = "Allow" 88 | actions = [ 89 | "ecr:GetDownloadUrlForLayer", 90 | "ecr:BatchGetImage", 91 | "ecr:DescribeImages", 92 | "ecr:GetAuthorizationToken", 93 | "ecr:BatchCheckLayerAvailability" 94 | ] 95 | resources = ["*"] 96 | } 97 | } 98 | 99 | 100 | dynamic "statement" { 101 | for_each = var.deploy_image_scanning_ecr || var.deploy_image_scanning_ecs ? [1] : [] 102 | content { 103 | sid = "AllowCodebuild" 104 | effect = "Allow" 105 | actions = [ 106 | "codebuild:StartBuild" 107 | ] 108 | resources = [var.build_project_arn] 109 | } 110 | } 111 | 112 | dynamic "statement" { 113 | for_each = var.deploy_image_scanning_ecr || var.deploy_beta_image_scanning_ecr ? [1] : [] 114 | content { 115 | sid = "AllowECS" 116 | effect = "Allow" 117 | actions = [ 118 | "ecs:DescribeTaskDefinition" 119 | ] 120 | resources = ["*"] 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /examples/single-account-k8s/diagram.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Cluster, Diagram, Edge, Node 3 | from diagrams.aws.general import General 4 | from diagrams.aws.compute import EKS, ECR 5 | from diagrams.aws.devtools import Codebuild 6 | from diagrams.aws.integration import SNS, SQS 7 | from diagrams.aws.management import Cloudtrail 8 | from diagrams.aws.security import IAM, IAMRole 9 | from diagrams.aws.storage import S3 10 | from diagrams.custom import Custom 11 | from diagrams.aws.compute import ECS, ElasticContainerServiceService, ECR 12 | 13 | from diagrams.k8s.group import Namespace 14 | from diagrams.k8s.compute import Deployment 15 | 16 | diagram_attr = { 17 | "pad":"1.25" 18 | } 19 | 20 | role_attr = { 21 | "imagescale":"true", 22 | "width":"2", 23 | "fontsize":"13", 24 | } 25 | 26 | color_event="firebrick" 27 | color_permission="steelblue3" 28 | color_creates="darkblue" 29 | color_non_important="gray" 30 | color_sysdig="lightblue" 31 | 32 | 33 | 34 | with Diagram("Sysdig Secure for Cloud{}(single-account-k8s)".format("\n"), graph_attr=diagram_attr, filename="diagram", show=True): 35 | 36 | public_registries = Custom("Public Registries","../../resources/diag-registry-icon.png") 37 | 38 | 39 | with Cluster("AWS single-account"): 40 | 41 | master_credentials = IAM("credentials \npermissions: cloudtrail, role creation,...", fontsize="10") 42 | 43 | with Cluster("other resources", graph_attr={"bgcolor":"lightblue"}): 44 | account_resources = [General("resource-1..n")] 45 | ecr = ECR("container-registry\n*sends events on image push to cloudtrail\n*within any account") 46 | 47 | with Cluster("ecs-cluster"): 48 | ecs_services = ElasticContainerServiceService("other services\n*sends events with image runs to cloudtrail") 49 | 50 | with Cluster("sysdig-secure-for-cloud resources"): 51 | 52 | cloudtrail = Cloudtrail("cloudtrail\n* ingest events from all\norg member accounts+managed", shape="plaintext") 53 | cloudtrail_s3 = S3("cloudtrail-s3-events") 54 | sns = SNS("sns") 55 | 56 | sqs = SQS("cloudtrail-sqs") 57 | 58 | cloudtrail >> Edge(color=color_event, style="dashed") >> cloudtrail_s3 59 | cloudtrail >> Edge(color=color_event, style="dashed") >> sns 60 | 61 | with Cluster(""): 62 | eks = Deployment() 63 | with Cluster("K8s Cluster\n(pre-existing)\nnamespace: sfc"): 64 | cloud_connector = Deployment("cloud-connector") 65 | 66 | 67 | # scanning 68 | codebuild = Codebuild("CodeBuild Project") 69 | cloud_connector >> codebuild 70 | codebuild >> Edge(color=color_non_important) >> ecr 71 | codebuild >> Edge(color=color_non_important) >> public_registries 72 | 73 | # bench-role 74 | cloud_bench_role = IAMRole("SysdigCloudBench\n(aws:SecurityAudit policy)", **role_attr) 75 | 76 | sqs << Edge(color=color_event) << cloud_connector 77 | cloud_connector >> Edge(color=color_sysdig, style="dashed") >> sqs 78 | 79 | sns >> Edge(color=color_event, style="dashed") >> sqs 80 | (cloudtrail_s3 << Edge(color=color_non_important)) - cloud_connector 81 | 82 | 83 | with Cluster("AWS account (sysdig)"): 84 | sds = Custom("Sysdig Secure\n*receives cloud-connector and cloud-build results\n*assumeRole on SysdigCloudBench", "../../resources/diag-sysdig-icon.png") 85 | sds_account = General("cloud-bench") 86 | sds - Edge(label="aws_foundations_bench\n schedule on rand rand * * *") >> sds_account 87 | 88 | cloud_connector >> Edge(color=color_sysdig) >> sds 89 | codebuild >> Edge(color=color_sysdig) >> sds 90 | sds_account >> Edge(color=color_permission, fontcolor=color_permission) >> cloud_bench_role 91 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/s3.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "cloudtrail" { 2 | # AC_AWS_0214 3 | # Why: S3 bucket versioning is disabled 4 | #ts:skip=AC_AWS_0214 S3 is for testing purpose by the customer. In production S3 it's pretended to be provided by the customer with the logging related decisions taken by them as it has costs. 5 | # AC_AWS_0497 6 | # Why: S3 access logging is disabled 7 | #ts:skip=AC_AWS_0497 S3 is for testing purpose by the customer. In production S3 it's pretended to be provided by the customer with the logging related decisions taken by them as it has costs. 8 | bucket = "${var.name}-${data.aws_caller_identity.me.account_id}" 9 | force_destroy = true 10 | tags = var.tags 11 | } 12 | 13 | resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail" { 14 | bucket = aws_s3_bucket.cloudtrail.id 15 | rule { 16 | 17 | apply_server_side_encryption_by_default { 18 | sse_algorithm = var.cloudtrail_kms_enable ? "aws:kms" : "AES256" 19 | kms_master_key_id = var.cloudtrail_kms_enable ? aws_kms_key.cloudtrail_kms[0].id : null 20 | } 21 | } 22 | } 23 | 24 | resource "aws_s3_bucket_ownership_controls" "owner_enforced" { 25 | bucket = aws_s3_bucket.cloudtrail.id 26 | 27 | rule { 28 | object_ownership = "BucketOwnerEnforced" 29 | } 30 | } 31 | 32 | resource "aws_s3_bucket_lifecycle_configuration" "cloudtrail" { 33 | bucket = aws_s3_bucket.cloudtrail.id 34 | 35 | rule { 36 | id = "expire in ${var.s3_bucket_expiration_days} days" 37 | status = "Enabled" 38 | expiration { 39 | days = var.s3_bucket_expiration_days 40 | } 41 | } 42 | } 43 | 44 | 45 | # -------------------------- 46 | # iam, acl 47 | # ------------------------- 48 | 49 | resource "aws_s3_bucket_public_access_block" "cloudtrail" { 50 | count = var.temporary_s3_bucket_public_block == false ? 0 : 1 51 | bucket = aws_s3_bucket.cloudtrail.id 52 | block_public_acls = true 53 | block_public_policy = true 54 | ignore_public_acls = true 55 | restrict_public_buckets = true 56 | depends_on = [aws_s3_bucket_policy.cloudtrail_s3] 57 | # https://github.com/hashicorp/terraform-provider-aws/issues/7628 58 | } 59 | 60 | 61 | resource "aws_s3_bucket_policy" "cloudtrail_s3" { 62 | bucket = aws_s3_bucket.cloudtrail.id 63 | policy = data.aws_iam_policy_document.cloudtrail_s3.json 64 | } 65 | data "aws_iam_policy_document" "cloudtrail_s3" { 66 | statement { 67 | sid = "AWSCloudTrailAclCheck" 68 | effect = "Allow" 69 | principals { 70 | identifiers = ["cloudtrail.amazonaws.com"] 71 | type = "Service" 72 | } 73 | actions = ["s3:GetBucketAcl"] 74 | resources = [aws_s3_bucket.cloudtrail.arn] 75 | } 76 | 77 | statement { 78 | sid = "AWSCloudTrailWrite" 79 | effect = "Allow" 80 | principals { 81 | identifiers = ["cloudtrail.amazonaws.com"] 82 | type = "Service" 83 | } 84 | actions = ["s3:PutObject"] 85 | condition { 86 | variable = "s3:x-amz-acl" 87 | test = "StringEquals" 88 | values = ["bucket-owner-full-control"] 89 | } 90 | resources = ["${aws_s3_bucket.cloudtrail.arn}/AWSLogs/*"] 91 | } 92 | 93 | # S3 buckets should require requests to use Secure Socket Layer 94 | # [PCI.S3.5] This AWS control checks whether S3 buckets have policies that require requests to use Secure Socket Layer (SSL). 95 | statement { 96 | principals { 97 | identifiers = ["*"] 98 | type = "AWS" 99 | } 100 | actions = ["s3:*"] 101 | resources = [ 102 | aws_s3_bucket.cloudtrail.arn, 103 | "${aws_s3_bucket.cloudtrail.arn}/*" 104 | ] 105 | effect = "Deny" 106 | condition { 107 | test = "Bool" 108 | variable = "aws:SecureTransport" 109 | values = ["false"] 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /modules/infrastructure/codebuild/README.md: -------------------------------------------------------------------------------- 1 | # AWS Codebuild 2 | 3 | 4 | ## Requirements 5 | 6 | | Name | Version | 7 | |------|---------| 8 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 9 | | [aws](#requirement\_aws) | >= 3.50.0 | 10 | 11 | ## Providers 12 | 13 | | Name | Version | 14 | |------|---------| 15 | | [aws](#provider\_aws) | >= 3.50.0 | 16 | 17 | ## Modules 18 | 19 | No modules. 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_cloudwatch_log_group.log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | 26 | | [aws_codebuild_project.build_project](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_project) | resource | 27 | | [aws_iam_role.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 28 | | [aws_iam_role_policy.logs_publisher](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | 29 | | [aws_iam_role_policy.read_parameters](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | 30 | | [aws_caller_identity.me](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 31 | | [aws_iam_policy_document.logs_publisher](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 32 | | [aws_iam_policy_document.service_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 33 | | [aws_iam_policy_document.task_read_parameters](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 34 | | [aws_partition.current_partition](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | 35 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 36 | | [aws_ssm_parameter.sysdig_secure_api_token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | 37 | 38 | ## Inputs 39 | 40 | | Name | Description | Type | Default | Required | 41 | |------|-------------|------|---------|:--------:| 42 | | [secure\_api\_token\_secret\_name](#input\_secure\_api\_token\_secret\_name) | Sysdig Secure API token SSM parameter name | `string` | n/a | yes | 43 | | [cloudwatch\_log\_retention](#input\_cloudwatch\_log\_retention) | Days to keep logs from builds | `number` | `30` | no | 44 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc-codebuild"` | no | 45 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 46 | 47 | ## Outputs 48 | 49 | | Name | Description | 50 | |------|-------------| 51 | | [project\_arn](#output\_project\_arn) | Code Build project arn | 52 | | [project\_name](#output\_project\_name) | Code Build project name | 53 | 54 | 55 | ## Authors 56 | 57 | Module is maintained and supported by [Sysdig](https://sysdig.com). 58 | 59 | ## License 60 | 61 | Apache 2 Licensed. See LICENSE for full details. 62 | -------------------------------------------------------------------------------- /modules/infrastructure/cloudtrail/kms.tf: -------------------------------------------------------------------------------- 1 | resource "aws_kms_key" "cloudtrail_kms" { 2 | count = var.cloudtrail_kms_enable ? 1 : 0 3 | is_enabled = true 4 | enable_key_rotation = true 5 | policy = data.aws_iam_policy_document.cloudtrail_kms[0].json 6 | deletion_window_in_days = 7 7 | 8 | tags = var.tags 9 | } 10 | 11 | resource "aws_kms_alias" "kms" { 12 | count = var.cloudtrail_kms_enable ? 1 : 0 13 | target_key_id = aws_kms_key.cloudtrail_kms[0].id 14 | name = "alias/${var.name}" 15 | } 16 | 17 | data "aws_iam_policy_document" "cloudtrail_kms" { 18 | count = var.cloudtrail_kms_enable ? 1 : 0 19 | statement { 20 | sid = "Enable IAM User Permissions" 21 | effect = "Allow" 22 | principals { 23 | # identifiers = ["arn:aws:iam::${data.aws_caller_identity.me.account_id}:root"] 24 | identifiers = [data.aws_caller_identity.me.account_id] 25 | type = "AWS" 26 | } 27 | actions = ["kms:*"] 28 | resources = ["*"] 29 | } 30 | 31 | statement { 32 | sid = "Allow CloudTrail to encrypt logs" 33 | effect = "Allow" 34 | principals { 35 | identifiers = ["cloudtrail.amazonaws.com"] 36 | type = "Service" 37 | } 38 | actions = ["kms:GenerateDataKey*"] 39 | resources = ["*"] 40 | condition { 41 | test = "StringLike" 42 | values = ["arn:aws:cloudtrail:*:${data.aws_caller_identity.me.account_id}:trail/*"] 43 | variable = "kms:EncryptionContext:aws:cloudtrail:arn" 44 | } 45 | } 46 | 47 | 48 | statement { 49 | sid = "Allow CloudTrail to describe key" 50 | effect = "Allow" 51 | principals { 52 | identifiers = ["cloudtrail.amazonaws.com"] 53 | type = "Service" 54 | } 55 | actions = ["kms:DescribeKey"] 56 | resources = ["*"] 57 | } 58 | 59 | statement { 60 | sid = "Allow principals in the account to decrypt log files" 61 | effect = "Allow" 62 | principals { 63 | identifiers = ["*"] 64 | type = "AWS" 65 | } 66 | actions = ["kms:Decrypt", "kms:ReEncryptFrom"] 67 | resources = ["*"] 68 | condition { 69 | test = "StringEquals" 70 | values = [data.aws_caller_identity.me.account_id] 71 | variable = "kms:CallerAccount" 72 | } 73 | condition { 74 | test = "StringLike" 75 | values = ["arn:aws:cloudtrail:*:${data.aws_caller_identity.me.account_id}:trail/*"] 76 | variable = "kms:EncryptionContext:aws:cloudtrail:arn" 77 | } 78 | } 79 | 80 | statement { 81 | sid = "Allow alias creation during setup" 82 | effect = "Allow" 83 | principals { 84 | identifiers = ["*"] 85 | type = "AWS" 86 | } 87 | actions = ["kms:CreateAlias"] 88 | resources = ["*"] 89 | condition { 90 | test = "StringEquals" 91 | values = ["ec2.${data.aws_caller_identity.me.account_id}.amazonaws.com"] 92 | variable = "kms:ViaService" 93 | } 94 | condition { 95 | test = "StringEquals" 96 | values = [data.aws_caller_identity.me.account_id] 97 | variable = "kms:CallerAccount" 98 | } 99 | } 100 | 101 | 102 | statement { 103 | sid = "Enable cross account log decryption" 104 | effect = "Allow" 105 | # principals { 106 | # identifiers = ["*"] 107 | # type = "AWS" 108 | # } 109 | principals { 110 | identifiers = ["ecs-tasks.amazonaws.com"] 111 | type = "Service" 112 | } 113 | actions = ["kms:Decrypt", "kms:ReEncryptFrom"] 114 | resources = ["*"] 115 | # condition { 116 | # test = "StringEquals" 117 | # values = [data.aws_caller_identity.me.account_id] 118 | # variable = "kms:CallerAccount" 119 | # } 120 | # condition { 121 | # test = "StringLike" 122 | # values = ["arn:aws:cloudtrail:*:${data.aws_caller_identity.me.account_id}:trail/*"] 123 | # variable = "kms:EncryptionContext:aws:cloudtrail:arn" 124 | # } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /modules/services/cloud-connector-ecs/ecs-service-autoscaling.tf: -------------------------------------------------------------------------------- 1 | resource "aws_appautoscaling_target" "ecs_target" { 2 | count = var.enable_autoscaling ? 1 : 0 3 | 4 | max_capacity = var.autoscaling_config.max_replicas 5 | min_capacity = var.autoscaling_config.min_replicas 6 | resource_id = "service/${local.sanitized_cluster_name}/${var.name}" 7 | scalable_dimension = "ecs:service:DesiredCount" 8 | service_namespace = "ecs" 9 | 10 | depends_on = [aws_ecs_service.service] 11 | } 12 | 13 | 14 | # upscale memory > threshold 15 | resource "aws_appautoscaling_policy" "ecs_memory_above" { 16 | count = var.enable_autoscaling ? 1 : 0 17 | 18 | name = "scale-cloud-connector-ram-above" 19 | policy_type = "StepScaling" 20 | resource_id = aws_appautoscaling_target.ecs_target[0].resource_id 21 | scalable_dimension = aws_appautoscaling_target.ecs_target[0].scalable_dimension 22 | service_namespace = aws_appautoscaling_target.ecs_target[0].service_namespace 23 | 24 | step_scaling_policy_configuration { 25 | adjustment_type = "ChangeInCapacity" 26 | cooldown = 30 27 | metric_aggregation_type = "Average" 28 | 29 | step_adjustment { 30 | metric_interval_lower_bound = 0 31 | scaling_adjustment = 1 32 | } 33 | } 34 | } 35 | 36 | resource "aws_cloudwatch_metric_alarm" "ecs_memory_above" { 37 | count = var.enable_autoscaling ? 1 : 0 38 | 39 | alarm_name = "Step-Scaling-Alarm-Upscale-ECS:service/${local.sanitized_cluster_name}/${aws_ecs_service.service.name}" 40 | alarm_description = "ECS cloud-connector service is above memory utilization threshold" 41 | 42 | metric_name = "MemoryUtilization" 43 | namespace = "AWS/ECS" 44 | statistic = "Average" 45 | 46 | period = "60" # minimum 60 seconds 47 | evaluation_periods = "1" 48 | 49 | comparison_operator = "GreaterThanOrEqualToThreshold" 50 | threshold = var.autoscaling_config.upscale_threshold 51 | alarm_actions = [aws_appautoscaling_policy.ecs_memory_above[0].arn] 52 | 53 | dimensions = { 54 | ClusterName = local.sanitized_cluster_name, 55 | ServiceName = aws_ecs_service.service.name 56 | } 57 | 58 | depends_on = [aws_ecs_service.service] 59 | } 60 | 61 | 62 | 63 | # downscale memory > threshold 64 | resource "aws_appautoscaling_policy" "ecs_memory_below" { 65 | count = var.enable_autoscaling ? 1 : 0 66 | 67 | name = "scale-cloud-connector-ram-below" 68 | policy_type = "StepScaling" 69 | resource_id = aws_appautoscaling_target.ecs_target[0].resource_id 70 | scalable_dimension = aws_appautoscaling_target.ecs_target[0].scalable_dimension 71 | service_namespace = aws_appautoscaling_target.ecs_target[0].service_namespace 72 | 73 | step_scaling_policy_configuration { 74 | adjustment_type = "ChangeInCapacity" 75 | cooldown = 30 76 | metric_aggregation_type = "Average" 77 | 78 | step_adjustment { 79 | metric_interval_upper_bound = 0 80 | metric_interval_lower_bound = -10 81 | scaling_adjustment = 0 82 | } 83 | 84 | step_adjustment { 85 | metric_interval_upper_bound = -10 86 | scaling_adjustment = -1 87 | } 88 | } 89 | } 90 | 91 | resource "aws_cloudwatch_metric_alarm" "ecs_memory_below" { 92 | count = var.enable_autoscaling ? 1 : 0 93 | 94 | alarm_name = "Step-Scaling-Alarm-Dowscale-ECS:service/${local.sanitized_cluster_name}/${aws_ecs_service.service.name}" 95 | alarm_description = "ECS cloud-connector service is below memory utilization threshold" 96 | 97 | metric_name = "MemoryUtilization" 98 | namespace = "AWS/ECS" 99 | statistic = "Average" 100 | 101 | period = "60" # minimum 60 seconds 102 | evaluation_periods = "1" 103 | 104 | threshold = var.autoscaling_config.downscale_threshold 105 | comparison_operator = "LessThanThreshold" 106 | alarm_actions = [aws_appautoscaling_policy.ecs_memory_below[0].arn] 107 | 108 | dimensions = { 109 | ClusterName = local.sanitized_cluster_name, 110 | ServiceName = aws_ecs_service.service.name 111 | } 112 | 113 | depends_on = [aws_ecs_service.service] 114 | } 115 | -------------------------------------------------------------------------------- /examples/single-account-apprunner/diagram-single.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Diagram, Cluster, Diagram, Edge, Node 3 | from diagrams.custom import Custom 4 | from diagrams.aws.general import General 5 | from diagrams.aws.management import Cloudtrail 6 | from diagrams.aws.storage import S3, SimpleStorageServiceS3Bucket 7 | from diagrams.aws.integration import SNS 8 | from diagrams.aws.integration import SQS 9 | from diagrams.aws.compute import ECS, ElasticContainerServiceService, ECR 10 | from diagrams.aws.security import IAMRole,IAM 11 | from diagrams.aws.management import Cloudwatch 12 | from diagrams.aws.devtools import Codebuild 13 | 14 | 15 | diagram_attr = { 16 | "pad":"1.25" 17 | } 18 | 19 | 20 | role_attr = { 21 | "imagescale":"true", 22 | "width":"2", 23 | "fontsize":"13", 24 | } 25 | 26 | 27 | color_event="firebrick" 28 | color_scanning = "dark-green" 29 | color_permission="steelblue3" 30 | color_non_important="gray" 31 | color_sysdig="lightblue" 32 | 33 | with Diagram("Sysdig Secure for Cloud{}(single-account)".format("\n"), graph_attr=diagram_attr, filename="diagram-single", show=True): 34 | 35 | public_registries = Custom("Public Registries","../../resources/diag-registry-icon.png") 36 | 37 | 38 | with Cluster("AWS single-account"): 39 | 40 | master_credentials = IAM("credentials \npermissions: cloudtrail, role creation,...", fontsize="10") 41 | 42 | with Cluster("other resources", graph_attr={"bgcolor":"lightblue"}): 43 | account_resources = [General("resource-1..n")] 44 | ecr = ECR("container-registry\n*sends events on image push to cloudtrail\n*within any account") 45 | 46 | with Cluster("app-runner"): 47 | ecs_services = ElasticContainerServiceService("other services\n*sends events with image runs to cloudtrail") 48 | 49 | with Cluster("sysdig-secure-for-cloud resources"): 50 | 51 | # cloudtrail 52 | cloudtrail = Cloudtrail("cloudtrail\n* ingest events from all\norg member accounts+managed", shape="plaintext") 53 | # cloudtrail_legend = ("for clarity purpose events received from sysdig-secure-for-cloud resources\nhave been removed from diagram, but will be processed too") 54 | # Node(label=cloudtrail_legend, width="5",shape="plaintext", labelloc="t", fontsize="10") 55 | 56 | cloudtrail_s3 = S3("cloudtrail-s3-events") 57 | sns = SNS("cloudtrail-sns-events", comment="i'm a graph") 58 | cloudwatch = Cloudwatch("cloudwatch\n(logs and alarms)") 59 | 60 | 61 | cloudtrail >> Edge(color=color_event, style="dashed") >> cloudtrail_s3 62 | cloudtrail >> Edge(color=color_event, style="dashed") >> sns 63 | 64 | with Cluster("AppRunner"): 65 | cloud_connector = Custom("cloud-connector", "../../resources/apprunner-icon.png") 66 | 67 | sqs = SQS("cloudtrail-sqs") 68 | sqs << Edge(color=color_event) << cloud_connector 69 | cloud_connector >> Edge(color=color_non_important) >> cloudwatch 70 | 71 | # scanning 72 | codebuild = Codebuild("CodeBuild Project") 73 | cloud_connector >> Edge(color=color_non_important) >> cloudwatch 74 | cloud_connector >> codebuild 75 | codebuild >> Edge(color=color_non_important) >> ecr 76 | codebuild >> Edge(color=color_non_important) >> public_registries 77 | 78 | 79 | # bench-role 80 | cloud_bench_role = IAMRole("SysdigCloudBench\n(aws:SecurityAudit policy)", **role_attr) 81 | 82 | #account_resources >> Edge(color=color_event, style="dashed") >> cloudtrail 83 | sns >> Edge(color=color_event, style="dashed") >> sqs 84 | (cloudtrail_s3 << Edge(color=color_non_important)) - cloud_connector 85 | 86 | with Cluster("AWS account (sysdig)"): 87 | sds = Custom("Sysdig Secure\n*receives cloud-connector and cloud-build results\n*assumeRole on SysdigCloudBench", "../../resources/diag-sysdig-icon.png") 88 | sds_account = General("cloud-bench") 89 | sds - Edge(label="aws_foundations_bench\n schedule on rand rand * * *") >> sds_account 90 | 91 | 92 | cloud_connector >> Edge(color=color_sysdig) >> sds 93 | codebuild >> Edge(color=color_sysdig) >> sds 94 | sds_account >> Edge(color=color_permission, fontcolor=color_permission) >> cloud_bench_role 95 | -------------------------------------------------------------------------------- /examples/single-account-ecs/diagram-single.py: -------------------------------------------------------------------------------- 1 | # diagrams as code vía https://diagrams.mingrammer.com 2 | from diagrams import Diagram, Cluster, Diagram, Edge, Node 3 | from diagrams.custom import Custom 4 | from diagrams.aws.general import General 5 | from diagrams.aws.management import Cloudtrail 6 | from diagrams.aws.storage import S3, SimpleStorageServiceS3Bucket 7 | from diagrams.aws.integration import SNS 8 | from diagrams.aws.integration import SQS 9 | from diagrams.aws.compute import ECS, ElasticContainerServiceService, ECR 10 | from diagrams.aws.security import IAMRole,IAM 11 | from diagrams.aws.management import Cloudwatch 12 | from diagrams.aws.devtools import Codebuild 13 | from diagrams.aws.management import SystemsManager 14 | 15 | 16 | diagram_attr = { 17 | "pad":"1.25" 18 | } 19 | 20 | 21 | role_attr = { 22 | "imagescale":"true", 23 | "width":"2", 24 | "fontsize":"13", 25 | } 26 | 27 | 28 | color_event="firebrick" 29 | color_scanning = "dark-green" 30 | color_permission="steelblue3" 31 | color_non_important="gray" 32 | color_sysdig="lightblue" 33 | 34 | with Diagram("Sysdig Secure for Cloud{}(single-account-ecs)".format("\n"), graph_attr=diagram_attr, filename="diagram-single", show=True): 35 | 36 | public_registries = Custom("Public Registries","../../resources/diag-registry-icon.png") 37 | 38 | 39 | with Cluster("AWS single-account-ecs"): 40 | 41 | master_credentials = IAM("credentials \npermissions: cloudtrail, role creation,...", fontsize="10") 42 | 43 | with Cluster("other resources", graph_attr={"bgcolor":"lightblue"}): 44 | account_resources = [General("resource-1..n")] 45 | ecr = ECR("container-registry\n*sends events on image push to cloudtrail\n*within any account") 46 | 47 | with Cluster("ecs-cluster"): 48 | ecs_services = ElasticContainerServiceService("other services\n*sends events with image runs to cloudtrail") 49 | 50 | with Cluster("sysdig-secure-for-cloud resources"): 51 | 52 | # cloudtrail 53 | cloudtrail = Cloudtrail("cloudtrail\n* ingest events from all\norg member accounts+managed", shape="plaintext") 54 | # cloudtrail_legend = ("for clarity purpose events received from sysdig-secure-for-cloud resources\nhave been removed from diagram, but will be processed too") 55 | # Node(label=cloudtrail_legend, width="5",shape="plaintext", labelloc="t", fontsize="10") 56 | 57 | cloudtrail_s3 = S3("cloudtrail-s3-events") 58 | sns = SNS("cloudtrail-sns-events", comment="i'm a graph") 59 | cloudwatch = Cloudwatch("cloudwatch\n(logs and alarms)") 60 | 61 | 62 | cloudtrail >> Edge(color=color_event, style="dashed") >> cloudtrail_s3 63 | cloudtrail >> Edge(color=color_event, style="dashed") >> sns 64 | 65 | with Cluster("ecs-cluster"): 66 | cloud_connector = ElasticContainerServiceService("cloud-connector") 67 | 68 | sqs = SQS("cloudtrail-sqs") 69 | sqs << Edge(color=color_event) << cloud_connector 70 | cloud_connector >> Edge(color=color_non_important) >> cloudwatch 71 | 72 | # scanning 73 | codebuild = Codebuild("CodeBuild Project") 74 | cloud_connector >> Edge(color=color_non_important) >> cloudwatch 75 | cloud_connector >> codebuild 76 | codebuild >> Edge(color=color_non_important) >> ecr 77 | codebuild >> Edge(color=color_non_important) >> public_registries 78 | 79 | 80 | # bench-role 81 | cloud_bench_role = IAMRole("SysdigCloudBench\n(aws:SecurityAudit policy)", **role_attr) 82 | 83 | #account_resources >> Edge(color=color_event, style="dashed") >> cloudtrail 84 | sns >> Edge(color=color_event, style="dashed") >> sqs 85 | (cloudtrail_s3 << Edge(color=color_non_important)) - cloud_connector 86 | 87 | with Cluster("AWS account (sysdig)"): 88 | sds = Custom("Sysdig Secure\n*receives cloud-connector and cloud-build results\n*assumeRole on SysdigCloudBench", "../../resources/diag-sysdig-icon.png") 89 | sds_account = General("cloud-bench") 90 | sds - Edge(label="aws_foundations_bench\n schedule on rand rand * * *") >> sds_account 91 | 92 | 93 | cloud_connector >> Edge(color=color_sysdig) >> sds 94 | codebuild >> Edge(color=color_sysdig) >> sds 95 | sds_account >> Edge(color=color_permission, fontcolor=color_permission) >> cloud_bench_role 96 | -------------------------------------------------------------------------------- /modules/infrastructure/permissions/org-role-eks/README.md: -------------------------------------------------------------------------------- 1 | # AWS Organizational Secure for Cloud Role for K8s 2 | 3 | The aim of this module is to manage the organizational **managed account** required role and permissions for threat-detection and image scanning modules to work properly. 4 | 5 | 1. Enables Cloudtrail SNS subscription permissions through a role specified within the Sysdig Secure workload **member account** 6 | 2. Creates a role in the organizational **managed account** with the required permissions 7 | 8 | * Threat-Detection 9 | * S3 Get and List permissions in order to fetch the events 10 | * SNS Subscription permissions in order to subscribe a topic to it 11 | 12 | * Image scanning 13 | * Enable this role to assumeRole to member accounts through the `organizational_role_per_account` role, 14 | in order to be able to fetch images that may be in member-account repositories 15 | 16 | 17 | 18 | ## Requirements 19 | 20 | | Name | Version | 21 | |------|---------| 22 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 23 | | [aws](#requirement\_aws) | >= 3.50.0 | 24 | 25 | ## Providers 26 | 27 | | Name | Version | 28 | |------|---------| 29 | | [aws](#provider\_aws) | >= 3.50.0 | 30 | 31 | ## Modules 32 | 33 | No modules. 34 | 35 | ## Resources 36 | 37 | | Name | Type | 38 | |------|------| 39 | | [aws_iam_role.secure_for_cloud_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 40 | | [aws_iam_role_policy.sysdig_secure_for_cloud_role_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | 41 | | [aws_iam_role_policy.sysdig_secure_for_cloud_role_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | 42 | | [aws_iam_policy_document.sysdig_secure_for_cloud_role_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 43 | | [aws_iam_policy_document.sysdig_secure_for_cloud_role_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 44 | | [aws_iam_policy_document.sysdig_secure_for_cloud_role_trusted](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 45 | 46 | ## Inputs 47 | 48 | | Name | Description | Type | Default | Required | 49 | |------|-------------|------|---------|:--------:| 50 | | [cloudtrail\_s3\_arn](#input\_cloudtrail\_s3\_arn) | Cloudtrail S3 bucket ARN | `string` | n/a | yes | 51 | | [user\_arn](#input\_user\_arn) | ARN of the IAM user to which roles will be added | `string` | n/a | yes | 52 | | [deploy\_image\_scanning](#input\_deploy\_image\_scanning) | true/false whether to provision cloud\_scanning permissions | `bool` | `true` | no | 53 | | [name](#input\_name) | Name to be assigned to all child resources. A suffix may be added internally when required. Use default value unless you need to install multiple instances | `string` | `"sfc"` | no | 54 | | [organizational\_role\_per\_account](#input\_organizational\_role\_per\_account) | Name of the organizational role deployed by AWS in each account of the organization | `string` | `"OrganizationAccountAccessRole"` | no | 55 | | [tags](#input\_tags) | customization of tags to be assigned to all resources.
always include 'product' default tag for resource-group proper functioning.
can also make use of the [provider-level `default-tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) | `map(string)` |
{
"product": "sysdig-secure-for-cloud"
}
| no | 56 | 57 | ## Outputs 58 | 59 | | Name | Description | 60 | |------|-------------| 61 | | [sysdig\_secure\_for\_cloud\_role\_arn](#output\_sysdig\_secure\_for\_cloud\_role\_arn) | organizational secure-for-cloud role arn | 62 | | [sysdig\_secure\_for\_cloud\_role\_name](#output\_sysdig\_secure\_for\_cloud\_role\_name) | organizational secure-for-cloud role name | 63 | 64 | 65 | ## Authors 66 | 67 | Module is maintained and supported by [Sysdig](https://sysdig.com). 68 | 69 | ## License 70 | 71 | Apache 2 Licensed. See LICENSE for full details. 72 | -------------------------------------------------------------------------------- /examples/organizational/main.tf: -------------------------------------------------------------------------------- 1 | #------------------------------------- 2 | # resources deployed always in management account 3 | # with default provider 4 | #------------------------------------- 5 | locals { 6 | deploy_same_account = data.aws_caller_identity.me.account_id == var.sysdig_secure_for_cloud_member_account_id 7 | deploy_old_image_scanning_with_codebuild = (var.deploy_image_scanning_ecr && !var.deploy_beta_image_scanning_ecr) || var.deploy_image_scanning_ecs 8 | } 9 | 10 | module "resource_group" { 11 | source = "../../modules/infrastructure/resource-group" 12 | name = var.name 13 | tags = var.tags 14 | } 15 | 16 | module "resource_group_secure_for_cloud_member" { 17 | count = local.deploy_same_account ? 0 : 1 18 | providers = { 19 | aws = aws.member 20 | } 21 | source = "../../modules/infrastructure/resource-group" 22 | name = var.name 23 | tags = var.tags 24 | } 25 | 26 | #------------------------------------- 27 | # secure-for-cloud member account workload 28 | #------------------------------------- 29 | module "ssm" { 30 | providers = { 31 | aws = aws.member 32 | } 33 | source = "../../modules/infrastructure/ssm" 34 | name = var.name 35 | sysdig_secure_api_token = data.sysdig_secure_connection.current.secure_api_token 36 | tags = var.tags 37 | } 38 | 39 | 40 | #------------------------------------- 41 | # cloud-connector 42 | #------------------------------------- 43 | module "codebuild" { 44 | count = local.deploy_old_image_scanning_with_codebuild ? 1 : 0 45 | 46 | providers = { 47 | aws = aws.member 48 | } 49 | source = "../../modules/infrastructure/codebuild" 50 | name = var.name 51 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 52 | 53 | tags = var.tags 54 | # note. this is required to avoid race conditions 55 | depends_on = [module.ssm] 56 | } 57 | 58 | module "cloud_connector" { 59 | providers = { 60 | aws = aws.member 61 | } 62 | 63 | source = "../../modules/services/cloud-connector-ecs" 64 | name = "${var.name}-cloudconnector" 65 | 66 | secure_api_token_secret_name = module.ssm.secure_api_token_secret_name 67 | 68 | deploy_beta_image_scanning_ecr = var.deploy_beta_image_scanning_ecr 69 | deploy_image_scanning_ecr = var.deploy_image_scanning_ecr 70 | deploy_image_scanning_ecs = var.deploy_image_scanning_ecs 71 | 72 | # 73 | # note; 74 | # these two variables `is_organizational` and `organizational_config` is for image-scanning requirements (double inception) 75 | # this must still be true to be able to handle future image-scanning 76 | # is_organizational means that it will attempt an assumeRole on management account, as cloud_connector is deployed on `aws.member` alias 77 | # 78 | # TODO 79 | # - avoid all these parameters if `deploy_image_scanning_ecr` and `deploy_image_scanning_ecs` == false 80 | # - is_organizational to be renamed to enable_management_account_assume_role? 81 | # - we could check whether aws.member = aws (management account) infer the value of the variable 82 | # 83 | is_organizational = true 84 | organizational_config = { 85 | # see local.deploy_org_management_sysdig_role notes 86 | sysdig_secure_for_cloud_role_arn = local.deploy_org_management_sysdig_role ? module.secure_for_cloud_role[0].sysdig_secure_for_cloud_role_arn : var.existing_cloudtrail_config.cloudtrail_s3_role_arn 87 | organizational_role_per_account = var.organizational_member_default_admin_role 88 | connector_ecs_task_role_name = aws_iam_role.connector_ecs_task.name 89 | } 90 | 91 | build_project_arn = length(module.codebuild) == 1 ? module.codebuild[0].project_arn : "na" 92 | build_project_name = length(module.codebuild) == 1 ? module.codebuild[0].project_name : "na" 93 | 94 | existing_cloudtrail_config = { 95 | cloudtrail_sns_arn = local.cloudtrail_sns_arn 96 | cloudtrail_s3_sns_sqs_url = var.existing_cloudtrail_config.cloudtrail_s3_sns_sqs_url 97 | cloudtrail_s3_sns_sqs_arn = var.existing_cloudtrail_config.cloudtrail_s3_sns_sqs_arn 98 | } 99 | 100 | ecs_cluster_name = local.ecs_cluster_name 101 | ecs_vpc_id = local.ecs_vpc_id 102 | ecs_vpc_subnets_private_ids = local.ecs_vpc_subnets_private_ids 103 | ecs_task_cpu = var.ecs_task_cpu 104 | ecs_task_memory = var.ecs_task_memory 105 | 106 | enable_autoscaling = var.enable_autoscaling 107 | autoscaling_config = { 108 | min_replicas = var.autoscaling_config.min_replicas 109 | max_replicas = var.autoscaling_config.max_replicas 110 | upscale_threshold = var.autoscaling_config.upscale_threshold 111 | downscale_threshold = var.autoscaling_config.downscale_threshold 112 | } 113 | 114 | tags = var.tags 115 | depends_on = [local.cloudtrail_sns_arn, module.ssm] 116 | } 117 | --------------------------------------------------------------------------------