Cloud permissions
The minimum IAM permissions ZopNight needs on AWS, GCP, and Azure to pull metrics and act on resources.
ZopNight runs in read-only mode by default; discovery, recommendations, cost tracking, and metrics all work with the minimum permissions on this page. Read-write features (start/stop, auto-remediation, autoscaler write mode) need additional permissions you grant explicitly per cloud account.
This page covers the minimum policy each cloud needs. Per-service add-ons are linked from each section.
AWS. IAM policy for the aggregator
The aggregator pulls CloudWatch metrics and EBS/EC2 resource shapes. Attach this policy to the IAM user or role you give ZopNight.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "CloudWatchRead", "Effect": "Allow", "Action": [ "cloudwatch:GetMetricStatistics", "cloudwatch:GetMetricData", "cloudwatch:ListMetrics" ], "Resource": "*" }, { "Sid": "EC2DescribeForResourceShape", "Effect": "Allow", "Action": [ "ec2:DescribeVolumes", "ec2:DescribeInstances", "ec2:DescribeRegions" ], "Resource": "*" } ]}Namespaces ZopNight queries
The CloudWatch policy lets ZopNight read metrics in these namespaces:
AWS/EC2, AWS/EBS, AWS/RDS, AWS/Lambda, AWS/ElastiCache, AWS/MemoryDB, AWS/Redshift, AWS/OpenSearchService, AWS/DynamoDB, AWS/DocDB, AWS/Neptune, AWS/SQS, AWS/SNS, AWS/CloudFront, AWS/NATGateway, AWS/TransitGateway, AWS/Kafka, AWS/Kinesis, AWS/SageMaker, AWS/Bedrock, AWS/ElasticMapReduce, AWS/AppStream, AWS/WorkSpaces, AWS/ApiGateway, AWS/EFS, AWS/ApplicationELB, AWS/NetworkELB, AWS/EC2/Spot, AWS/S3-RequestMetrics.
Discovery permissions
The policy above covers metrics. Discovery uses Resource Explorer 2 plus per-service describe calls: for the full discoverer permission set, the simplest path is to attach the AWS-managed ReadOnlyAccess policy on top of the metrics policy above.
Billing data (for actual cost in Reports)
To replace rack-rate calculation with real billing cost in Reports, ZopNight needs AWS Cost Explorer access. Attach this policy in addition to the above:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "ce:GetCostAndUsage", "ce:GetCostAndUsageWithResources", "ce:GetTags" ], "Resource": "*" }]}Without this, the org falls back to rack rate. With it on every account in the org, Reports shows real billing cost.
Start / Stop (opt-in)
For ZopNight to actually stop and start resources via schedules, autoscaler, or auto-remediation, you need the corresponding action permissions per service. For EC2 start/stop, attach this policy in addition to the read policies above:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "ec2:StartInstances", "ec2:StopInstances" ], "Resource": "*" }]}Other services follow the same shape (rds:StopDBInstance, rds:StartDBInstance, and so on). Contact support for the full per-service write policy template.
Azure. Service Principal role assignments
When using the Service Principal method, ZopNight authenticates with clientId / clientSecret / tenantId / subscriptionId; Workload Identity Federation is also supported. Whichever Azure auth method you pick, the minimum role assignment is:
Role: Monitoring ReaderScope: /subscriptions/{subscriptionId}Monitoring Reader includes Microsoft.Insights/metrics/read on every resource in the subscription; that’s what the disk metrics fetcher needs to read OS Disk / Data Disk queue depth and latency gauges.
Billing data
Azure billing data uses the Cost Management Reader role on the billing scope, plus the amortized cost export type so reservation and savings-plan purchases attribute correctly per resource per day. With actual-cost mode at subscription scope, reserved VMs show $0; amortized fixes this.
Start / Stop / deallocate (opt-in)
For VM lifecycle actions, ZopNight needs Microsoft.Compute/virtualMachines/start/action, /restart/action, /deallocate/action. The Virtual Machine Contributor built-in covers these. For AKS scaling, add Azure Kubernetes Service Cluster User Role and Azure Kubernetes Service Contributor Role.
GCP. Service Account roles
For the Service Account Key method, ZopNight authenticates with a service-account JSON; One-Click Connect uses a managed service account instead. Whichever auth method you pick, the minimum role is:
Role: roles/monitoring.viewerScope: project (the GCP project that owns the resources)This includes monitoring.timeSeries.list; used by the disk fetcher to read compute.googleapis.com/instance/disk/read_latencies, write latencies, and throttled read/write op counts. The same role covers the GCS access-rate fetcher, Pub/Sub topic fetcher, GCP load-balancer fetcher, and Cloud SQL fetcher.
Cloud Asset Inventory (for discovery)
Add roles/cloudasset.viewer for resource discovery. This is what powers the Cloud Asset Inventory sweep that finds 80+ resource types per GCP project.
Billing data
For real billing cost in Reports, ZopNight reads from BigQuery billing exports. Add roles/bigquery.dataViewer and roles/bigquery.jobUser on the billing project, plus the billing export configured at the GCP organisation level. Contact support for the BigQuery dataset configuration.
Start / Stop (opt-in)
For Compute Engine lifecycle, roles/compute.instanceAdmin.v1. For GKE, roles/container.developer (or container.admin for namespace operations).
IAM Import (optional)
To pull GCP IAM members and bindings for the Cloud IAM Import wizard, roles/iam.securityReviewer. To also pull Google Group members, roles/cloudidentity.groups.reader at the organisation level (not project level).
Per-account discovery health
After connecting an account, the per-resource-type discovery success or failure is recorded in ZopNight. From Settings → Cloud accounts → View Permissions, you’ll see a drawer grouped by category (Compute, Database, Storage, Kubernetes, etc.) with per-resource-type status:
Granted
The resource type was discovered successfully on the last sweep.
Denied
The cloud API returned AccessDenied / 403 / AuthorizationFailed. Click the row to see the exact error and which permission to grant.
Unknown
No determination yet. Either the discovery hasn’t run, or the resource type isn’t relevant to this account.
Denied entries auto-skip in the periodic 6-hour discovery cron for 24 hours, so a permission gap doesn’t cost you repeated failed API calls. Manual refresh always retries everything: use it after granting the missing role to pick up the newly-allowed resource types immediately.
Metric coverage check
After you’ve granted permissions and run a fresh metrics sync, verify that the recommender is getting the metrics it expects. From Settings → Cloud accounts → View Permissions, a resource type whose metrics are flowing shows as Granted; the goal is for every relevant resource type to reach Granted after a manual refresh.
Any resource type still missing metrics points at either a permission gap or a discoverer enrichment issue. Grant the missing role and run a Manual refresh; if misses persist, contact support.
Validation summary
| Path | Validated against |
|---|---|
| AWS EBS in-use volume | Real CloudWatch data returned for VolumeQueueLength, VolumeTotalReadTime, VolumeTotalWriteTime, VolumeReadOps, VolumeWriteOps over 90-day window |
| AWS EBS idle volume | Empty result returned (correct behaviour; idle volumes have no metrics) |
| Azure disk path | Wired and dispatched; live fetch needs the discoverer to enrich attachedTo metadata on the managed disk |
| GCP disk path | Wired and dispatched; resolves disk → instance via attachedTo metadata + instanceId on the parent VM |