LogoLogo
Log in|Playground
  • Welcome
    • Introduction
    • FAQ
  • Capabilities
    • Log Management
    • Infrastructure Monitoring
    • Application Performance Monitoring (APM)
      • Application Metrics
      • Traces
      • Supported Technologies
    • Real User Monitoring (RUM)
  • Getting Started
    • Requirements
      • Kubernetes requirements
      • Kernel requirements for eBPF sensor
      • CPU architectures
      • ClickHouse resources
    • Installation & updating
    • Connect Linux hosts
    • Connect RUM
    • 5 quick steps to get you started
    • groundcover MCP
      • Configure groundcover's MCP Server
      • Getting-started Prompts
      • Real-world Use Cases
  • Use groundcover
    • Monitors
      • Create a new Monitor
      • Issues page
      • Monitor List page
      • Silences page
      • Monitor Catalog page
      • Monitor YAML structure
      • Embedded Grafana Alerts
        • Create a Grafana alert
    • Dashboards
      • Create a dashboard
      • Embedded Grafana Dashboards
        • Create a Grafana dashboard
        • Build alerts & dashboards with Grafana Terraform provider
        • Using groundcover datasources in a Self-hosted Grafana
    • Insights
    • Explore & Monitors query builder
    • Workflows
      • Create a new Workflow
      • Workflow Examples
      • Alert Structure
    • Search & Filter
    • Issues
    • Role-Based Access Control (RBAC)
    • Service Accounts
    • API Keys
    • APIs
    • Log Patterns
    • Drilldown
    • Scraping custom metrics
      • Operator based metrics
      • kube-state-metrics
      • cadvisor metrics
    • Backup & Restore Metrics
    • Metrics & Labels
    • Add custom environment labels
    • Configuring Pipelines
      • Writing Remap Transforms
      • Logs Pipeline Examples
      • Traces Pipeline Examples
      • Logs to Events Pipeline Examples
      • Logs/Traces Sensitive Data Obfuscation
      • Sensitive Data Obfuscation using OTTL
      • Log Filtering using OTTL
    • Querying your groundcover data
      • Query your logs
        • Example queries
        • Logs alerting
      • Query your metrics
      • Querying you data using an API
      • Using KEDA autoscaler with groundcover
  • Log Parsing with OpenTelemetry Pipelines
  • Log and Trace Correlation
  • RUM
  • Customization
    • Customize deployment
      • Agents in host network mode
      • API Key Secret
      • Argo CD
      • On-premise deployment
      • Quay.io registry
      • Configuring sensor deployment coverage
      • Enabling SSL Tracing in Java Applications
    • Customize usage
      • Filtering Kubernetes entities
      • Custom data retention
      • Sensitive data obfuscation
      • Custom storage
      • Custom logs collection
      • Custom labels and annotations
        • Enrich logs and traces with pod labels & annotations
        • Enrich metrics with node labels
      • Disable tracing for specific protocols
      • Tuning resources
      • Controlling the eBPF sampling mechanism
  • Integrations
    • Overview
    • Workflow Integrations
      • Slack Webhook Integration
      • Opsgenie Integration
      • Webhook Integration
        • Incident.io
      • PagerDuty Integration
      • Jira Webhook Integration
      • Send groundcover Alerts to Email via Zapier
    • Data sources
      • OpenTelemetry
        • Traces & Logs
        • Metrics
      • Istio
      • AWS
        • Ingest CloudWatch Metrics
        • Ingest CloudWatch Logs
        • Ingest Logs Stored on S3
        • Integrate CloudWatch Grafana Datasource
      • GCP
        • Ingest Google Cloud Monitoring Metrics
        • Stream Logs using Pub/Sub
        • Integrate Google Cloud Monitoring Grafana Datasource
      • Azure
        • Ingest Azure Monitor Metrics
      • DataDog
        • Traces
        • Metrics
      • FluentBit
      • Fluentd
      • JSON Logs
    • 3rd-party metrics
      • ActiveMQ
      • Aerospike
      • Cassandra
      • CloudFlare
      • Consul
      • CoreDNS
      • Etcd
      • HAProxy
      • Harbor
      • JMeter
      • K6
      • Loki
      • Nginx
      • Pi-hole
      • Postfix
      • RabbitMQ
      • Redpanda
      • SNMP
      • Solr
      • Tomcat
      • Traefik
      • Varnish
      • Vertica
      • Zabbix
    • Source control (Gitlab/Github)
  • Architecture
    • Overview
    • inCloud Managed
      • Setup inCloud Managed with AWS
        • AWS PrivateLink Setup
        • EKS add-on
      • Setup inCloud Managed with GCP
      • Setup inCloud Managed with Azure
      • High Availability
      • Disaster Recovery
      • Ingestion Endpoints
      • Deploying in Sensor-Only mode
    • Security considerations
      • Okta SSO - onboarding
    • Service endpoints inside the cluster
  • Product Updates
    • What's new?
    • Earlier updates
      • 2025
        • Mar 2025
        • Feb 2025
        • Jan 2025
      • 2024
        • Dec 2024
        • Nov 2024
        • Oct 2024
        • Sep 2024
        • Aug 2024
        • July 2024
        • May 2024
        • Apr 2024
        • Mar 2024
        • Feb 2024
        • Jan 2024
      • 2023
        • Dec 2023
        • Nov 2023
        • Oct 2023
Powered by GitBook
On this page
  • Step 1: Allocate an AWS account to groundcover
  • Option A: Creating a new, dedicated sub-account
  • Option B: Use an existing AWS account
  • Choose your telemetry delivery method
  • Step 2: Ask for your External ID
  • Step 3: Setup a cross-account IAM role
  • Option A: Create groundcover Role via CloudFormation
  • 3.1 - Run groundcover CloudFormation
  • Option B: Create groundcover Role Manually
  • 3.1 - Create a Role
  • 3.2 - Select trusted entity
  • 3.3 - Name, review, and create
  • 3.4 - Trust relationships
  • 3.5 - Inline Policy
  • Step 4: Share the ARN & region
  • Step 5: Get installation values
  • Step 6: Deploy our sensors
Export as PDF
  1. Architecture
  2. inCloud Managed

Setup inCloud Managed with AWS

Last updated 1 month ago

inCloud Managed is one of our setup options, which install our platform's infrastructure in a cloud environment owned by your organization, allowing you to delegate its entire setup, update, and maintenance to groundcover.

Note: inCloud Managed is available exclusively to Enterprise users.

inCloud Managed requires to create an isolated account within your AWS organization, that will be managed by groundcover's control plane and will establish, configure, and maintain the infrastructure and workloads within the account. These include AWS VPC, S3, EKS, LB, etc.

To complete the installation of inCloud Managed (total estimated time: 1 hour) you will need to follow these steps, all of which are detailed in the guide that follows:

Step 1: Allocate an AWS account to groundcover

groundcover inCloud Managed can be deployed using one the following configurations:

In line with AWS’s recommended unit of containerization, the default and preferable option is to deploy in a dedicated AWS account. This acts as an identity, resources, quota and access management isolation boundary.

Option A: Creating a new, dedicated sub-account

Option B: Use an existing AWS account

If you prefer using a single account approach, inCloud Managed can also be deployed into an existing account, running alongside existing production workloads in your existing AWS account. To limit access and prevent resource collusion, we implement a “scoping territory” approach using ABAC tags for access control and VPC subnets for network control.

Choose your telemetry delivery method

By default, groundcover inCloud Managed deploys as a SaaS solution using ZTNA public, allowing you to deliver telemetry data securely over the public internet.

Prefer private networking is supported with Private Link.

Step 2: Ask for your External ID

Step 3: Setup a cross-account IAM role

The following guide will walk you through the steps required to setup this access.

Option A: Create groundcover Role via CloudFormation

3.1 - Run groundcover CloudFormation

Make sure to enter the external ID provided by groundcover.

Option B: Create groundcover Role Manually

3.1 - Create a Role

  1. Navigate to IAM -> Roles

  2. Click “Create role”

3.2 - Select trusted entity

  1. Trusted entity type: Select “AWS Account”

  2. An AWS account: Check "Another AWS account"; Account ID: 991078109329

  3. Make sure “Require MFA” is unchecked

  4. Click "Next"

  5. In the following screen, do not attach any managed permissions

  6. Click "Next"

Note: AWS can’t verify MFA login in cross-account operational mode. groundcover control-plane is enforcing strict security principals, including MFA.

3.3 - Name, review, and create

Fill in the following details:

  • Role name: Type groundcover-managed

  • Description: Optional field, your can write any free text description that can be helpful for you and others to understand this purpose of this role in the future (e.g. “app.groundcover.com control plane access”)

  • Tags: Type groundcover:access = read. You can also use specify additional workflow-oriented tags

Click "Create role"

3.4 - Trust relationships

Search for the newly created groundcover-managed role (or scroll down the list until you find it) and click on it.

Navigate to the "Trust relationships" screen.

Click "Edit trust policy"

Replace the statement with the following snippet:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::991078109329:role/control-plane"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<External ID: Enter your ID (shared with you by groundcover)>"
        }
      }
    }
  ]
}

Click "Update Policy"

3.5 - Inline Policy

Navigate to "Permissions" tab.

Click "Add permissions" -> "Create inline policy"

Click the “JSON” tab and paste the following policy into the text box:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Access",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"sts:GetCallerIdentity",
				"sts:SetSourceIdentity"
			]
		},
		{
			"Sid": "ConsoleAccess",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"elasticloadbalancing:Describe*",
				"eks:List*"
			]
		},
		{
			"Sid": "CostController",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"aws-portal:ViewBilling",
				"billing:Get*",
				"billing:List*",
				"ce:Describe*",
				"ce:Get*",
				"ce:List*",
				"cur:Get*",
				"cur:Describe*",
				"cur:PutReportDefinition"
			]
		},
		{
			"Sid": "HealthController",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"cloudwatch:Describe*",
				"cloudwatch:Get*",
				"cloudwatch:List*",
				"health:Describe*",
				"logs:Describe*",
				"logs:Filter*",
				"logs:List*",
				"logs:Start*",
				"logs:Stop*",
				"logs:Test*",
				"servicequotas:Get*",
				"servicequotas:List*",
				"ec2messages:Get*",
				"events:Describe*",
				"events:List*",
				"events:Test*"
			]
		},
		{
			"Sid": "HealthControllerLogsGet",
			"Effect": "Allow",
			"Resource": [
				"arn:aws:logs:*:*:log-group:*groundcover*"
			],
			"Action": [
				"logs:Get*"
			]
		},
		{
			"Sid": "DriftReconciler",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"iam:ListPolicies",
				"iam:ListRolePolicies",
				"iam:ListInstanceProfilesForRole",
				"iam:ListAttachedRolePolicies",
				"ec2:Describe*",
				"eks:Describe*"
			]
		},
		{
			"Sid": "DriftReconcilerServiceRoles",
			"Effect": "Allow",
			"Action": [
				"iam:CreateServiceLinkedRole",
				"iam:DeleteServiceLinkedRole",
				"iam:GetServiceLinkedRoleDeletionStatus"
			],
			"Resource": [
				"arn:aws:iam::*:role/aws-service-role/eks-nodegroup.amazonaws.com/*",
				"arn:aws:iam::*:role/aws-service-role/autoscaling.amazonaws.com/*",
				"arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/*",
				"arn:aws:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/*"
			]
		},
		{
			"Sid": "DriftReconcilerGetRole",
			"Effect": "Allow",
			"Action": [
				"iam:GetRole"
			],
			"Resource": [
				"arn:aws:iam::*:role/*groundcover*",
				"arn:aws:iam::*:role/aws-service-role/eks-nodegroup.amazonaws.com/*"
			]
		},
		{
			"Sid": "ControlPlaneEC2TagOnCreate",
			"Effect": "Allow",
			"Action": [
				"ec2:CreateTags"
			],
			"Resource": "*",
			"Condition": {
				"StringLike": {
					"ec2:CreateAction": [
						"Create*"
					]
				},
				"StringNotEquals": {
					"ec2:CreateAction": [
						"CreateTags"
					]
				}
			}
		},
		{
			"Sid": "ControlPlaneModifyUntagged",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ec2:ReplaceRouteTableAssociation",
				"ec2:DisassociateAddress",
				"logs:CreateLogDelivery",
				"logs:DeleteLogDelivery",
				"vpce:AllowMultiRegion"
			]
		},
		{
			"Sid": "ControlPlaneCreateTagged",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"acm:RequestCertificate",
				"ec2:AllocateAddress",
				"ec2:Create*",
				"ec2:Run*",
				"eks:CreateCluster",
				"eks:Tag*",
				"logs:Create*",
				"logs:Tag*",
				"iam:CreateRole",
				"iam:CreateOpenIDConnectProvider",
				"iam:Tag*"
			],
			"Condition": {
				"StringEquals": {
					"aws:RequestTag/groundcover:access": "owner"
				},
				"ForAnyValue:StringEquals": {
					"aws:TagKeys": [
						"groundcover:access"
					]
				}
			}
		},
		{
			"Sid": "ControlPlaneReadBygroundcoveraccess",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ec2:Get*",
				"iam:Get*"
			],
			"Condition": {
				"StringEquals": {
					"aws:ResourceTag/groundcover:access": "read"
				}
			}
		},
		{
			"Sid": "ControlPlaneModifyBygroundcoveraccess",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"acm:*",
				"ec2:*",
				"eks:*",
				"logs:*",
				"elasticloadbalancing:*",
				"iam:AddClientIDToOpenIDConnectProvider",
				"iam:Get*",
				"iam:Delete*",
				"iam:DetachRolePolicy",
				"iam:Tag*",
				"iam:Untag*",
				"iam:Update*"
			],
			"Condition": {
				"StringEquals": {
					"aws:ResourceTag/groundcover:access": "owner"
				}
			}
		},
		{
			"Sid": "ControlPlaneModifyTaggedByeksclusername",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ec2:*"
			],
			"Condition": {
				"StringLike": {
					"aws:ResourceTag/eks:cluster-name": "groundcover*"
				}
			}
		},
		{
			"Sid": "ControlPlaneModifyTaggedByawseksclusername",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ec2:*"
			],
			"Condition": {
				"StringLike": {
					"aws:ResourceTag/aws:eks:cluster-name": "groundcover*"
				}
			}
		},
		{
			"Sid": "ControlPlaneModifyTaggedByKubernetesCluster",
			"Effect": "Allow",
			"Resource": "*",
			"Action": [
				"ec2:*"
			],
			"Condition": {
				"StringLike": {
					"aws:ResourceTag/KubernetesCluster": "groundcover*"
				}
			}
		},
		{
			"Sid": "ControlPlaneEKSRoleAttachPolicy",
			"Effect": "Allow",
			"Action": [
				"iam:AttachRolePolicy"
			],
			"Resource": "arn:aws:iam::*:role/groundcover*",
			"Condition": {
				"ArnEquals": {
					"iam:PolicyARN": [
						"arn:aws:iam::aws:policy/AmazonEKSClusterPolicy",
						"arn:aws:iam::aws:policy/AmazonEKSServicePolicy",
						"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
						"arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy",
						"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
						"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
					]
				},
				"StringEquals": {
					"aws:ResourceTag/groundcover:access": "owner"
				}
			}
		},
		{
			"Sid": "ControlPlaneEKSPassRole",
			"Effect": "Allow",
			"Action": "iam:PassRole",
			"Resource": "arn:aws:iam::*:role/groundcover*",
			"Condition": {
				"StringEquals": {
					"iam:PassedToService": [
						"eks.amazonaws.com"
					]
				}
			}
		},
		{
			"Sid": "ControlPlaneEKSRoles",
			"Effect": "Allow",
			"Action": [
				"iam:PutRolePolicy"
			],
			"Resource": [
				"arn:aws:iam::*:role/groundcover*"
			]
		},
		{
			"Sid": "ControlPlaneS3",
			"Effect": "Allow",
			"Action": "s3:*",
			"Resource": [
				"arn:aws:s3:::groundcover*"
			]
		},
		{
			"Sid": "BillingIntegrationSQS",
			"Effect": "Allow",
			"Action": [
				"sqs:UntagQueue",
				"sqs:GetQueueAttributes",
				"sqs:ListQueueTags",
				"sqs:TagQueue",
				"sqs:DeleteQueue",
				"sqs:CreateQueue",
				"sqs:SetQueueAttributes"
			],
			"Resource": [
				"arn:aws:sqs:*:*:groundcover*"
			]
		},
		{
			"Sid": "BillingIntegration",
			"Effect": "Allow",
			"Action": [
				"bcm-data-exports:GetExport",
				"bcm-data-exports:ListTagsForResource",
				"bcm-data-exports:CreateExport",
				"bcm-data-exports:TagResource",
				"bcm-data-exports:DeleteExport",
				"bcm-data-exports:UntagResource"
			],
			"Resource": [
				"*"
			],
			"Condition": {
				"StringEquals": {
					"aws:ResourceTag/groundcover:access": "owner"
				}
			}
		}
	]
}

Click "Next"

Click “Review Policy”

Enter the following Policy name: inline-policy-2.4.6

Click “Create policy”

Step 4: Share the ARN & region

Security of groundcover Control-Plane

groundcover Control-Plane is a secure reconciliation controller designed to manage enterprise inCloud infrastructure environments. It is compliant with ISO-27001 and SOC-2 standards.

The control plane can securely access your groundcover-incloud account by using a cross-account IAM role.

Setting up groundcover inCloud does not require access to your production data or workloads, nor does it grant it such access.

Binding Access

To establish the Trust Relationship, please share the following information with groundcover.

  1. Go to IAM > Roles > groundcover-managed > Trust relationships

  2. Verify that the sts:ExternalId is as was provided by the groundcover team

  3. Take note of your ARN number, which you will need to share with the groundcover team using our shared Slack channel.

Example:

Step 5: Get installation values

After you share the ARN & Region with us, we will need to setup the backend. Once we do, we will share with you the configuration details required for you to complete Step 6 (below).

Step 6: Deploy our sensors


We recommend naming the account [groundcover-incloud] and placing the account in OU=Infrastructure/OU=Managed. For additional information please see (external link to a page on the AWS website).

Users on an (prerequisite for inCloud Managed) have access to a private support channel on Slack for their organization. Use that channel to let us know that you're ready to get started with the inCloud Managed setup and ask for your External ID. The groundcover team will share your External ID with you.

To grant our control-plane access to the account, we use AWS’s feature.

For quick integration, we recommend using our CloudFormation template to deploy the groundcover role inside the new account. for the CloudFormation template.

Log in as a privileged user to the AWS account chosen in .

Options: Check "Require external ID" and enter your External ID (see )

We create the inline policy to adhere to (external link to Wikipedia) by limiting access on IAM, EC2 and related services to the bare minimum required for control plane operations including: health monitoring, security patches, auto scaling and version updates.

The final step is to deploy our sensors into the environment. In order to do so, follow .

Establishing your best practice AWS environment
Enterprise plan
built-in access federation
Click here
security best practices
this guide
Step 1
Step 1