Outcome
By the end of this lesson, you will be able to configure cross-account credentials for AWS / GCP / Azure, explain how ZopNight’s keyless AWS role is trusted, and predict the discovery flow timing for a multi-account estate.
| Prerequisites | M3.4.L1 (why multi-account) · M3.4.L2 (hierarchy) |
| Time | 9 minutes |
1. Concept
ZopNight needs read access in every account to find resources and pull costs.
In ZopNight that access is set up account by account: one cloud account per AWS account, per GCP project, and per Azure subscription (or one Azure tenant, which fans out to its subscriptions). That works at three accounts and needs discipline at sixty, because somebody eventually forgets one.
What keeps it safe at scale is the credential, not the connection count. The recommended method on each cloud avoids a long-lived secret wherever the cloud allows it:
RECOMMENDED METHOD PER CLOUD: AWS a role in each account that trusts ZopNight's Google identity; no secret stored GCP One-Click Connect per project: ZopNight creates and manages its own service account there Azure service principal (recommended) or workload identity federation, per subscription or tenantAWS pattern: a keyless role per account
STEP 1: CREATE THE ROLE (one CloudFormation stack per account) In ZopNight, add an AWS account and choose WIF-Assume Role. ZopNight offers a CloudFormation quick-create link. The stack creates a role with this trust policy:
trust_policy: Principal: { Federated: <account>:oidc-provider/accounts.google.com } Action: sts:AssumeRoleWithWebIdentity Condition: { StringEquals: { accounts.google.com:aud: <ZopNight's Google service account id>, accounts.google.com:sub: <ZopNight's Google service account id> } }
STEP 2: PASTE THE ROLE ARN into ZopNight The stack outputs the role ARN.
STEP 3: ZOPNIGHT assumes the role on each use sts.AssumeRoleWithWebIdentity( RoleArn = <the role ARN you pasted>, WebIdentityToken = <short-lived token minted for ZopNight's Google service account> ) → returns temporary credentials → ZopNight uses them for discovery in that account → credentials expire automatically; next discovery re-issues
NO management-account credential, NO StackSet.Repeat the stack in each account you want connected.Static access keys and temporary credentials are also accepted, but they are secrets you have to manage, which is why the role is recommended.
GCP pattern: One-Click Connect per project
Two options, one recommended:
RECOMMENDED: One-Click Connect In ZopNight, add a GCP project and sign in with Google ZopNight creates a dedicated service account in the project and binds the roles for the permission level you chose
Pros: no key file for you to hold or rotate Cons: the signed-in user must be able to administer the project's IAM
ALTERNATIVE: Service-account JSON key Generate a JSON key for a service account you manage Grant it the roles ZopNight needs in the project Upload the JSON key to ZopNight
Pros: works where an interactive sign-in is not possible Cons: long-lived secret; rotation is manual; key compromise = read of that projectEither way, each project is its own cloud account. There is no organization-level GCP connection and no GCP workload-identity option.
Azure pattern: service principal
STEP 1: REGISTER an Azure AD application Portal → Azure AD → App registrations → New registration Note: tenant_id, application (client) ID
STEP 2: GRANT permissions Azure RBAC → Reader role on the subscription, or at the tenant level if you will connect the tenant
STEP 3: CREATE a credential Option A: Client secret (service principal; recommended method in ZopNight; manual rotation) Option B: Workload Identity Federation (federated OIDC credential; no client secret to store)
STEP 4: CONNECT in ZopNight at subscription or tenant scope tenant_id + app_id + credential A tenant connection discovers every subscription it can reach and creates a child cloud account for eachAzure is the one cloud where a single connection can cover many accounts.
Cross-account discovery flow
What happens at each discovery cycle, per connected AWS account:
T+0 ZopNight scheduled discovery task beginsT+10ms Mints a short-lived token for ZopNight's Google identity
For each connected AWS account:T+11ms Calls sts.AssumeRoleWithWebIdentity(role_arn, token)T+50ms AWS returns temporary credentialsT+51ms ZopNight begins discovery API calls: EC2: DescribeInstances, DescribeVolumes, ... S3: ListBuckets, GetBucketLocation, ... RDS: DescribeDBInstances, ... (parallel calls; rate-limited per AWS guidance)T+800ms Discovery complete for this accountT+810ms Resources persisted to ZopNight's databaseT+810ms Temporary credentials abandoned (no need to revoke; they expire automatically)T+811ms Next connected account; repeat
For an 8-account AWS estate: Total cycle: a few minutes for full discovery (parallelism reduces wall-clock time well below 8× single-account time)The short-lived credential lifecycle is what makes this safe at scale. With the recommended AWS method, ZopNight holds no long-lived secret for your accounts at all.
Credential rotation
AWS (role): Nothing to rotate; credentials are short-lived.AWS (keys): Rotate access keys yourself, then update them in ZopNight.
GCP (One-Click): Nothing for you to rotate; ZopNight manages its service account.GCP (JSON): Service-account keys must be rotated periodically. Recommended: every 90 days.
Azure: Client secrets rotate per Azure's expiration policy (default 1 year, configurable). WIF eliminates the secret.A maturity signal: orgs without ongoing credential rotation processes are usually using long-lived keys. Moving to the keyless methods reduces the rotation surface dramatically.
What discovery actually fetches
RESOURCE INVENTORY EC2, RDS, S3, Lambda, EKS, ECS, EBS, ELB, ALB, NLB, Route53, CloudFront, ... (similar surfaces for GCP and Azure)
COST DATA CUR (AWS), Cloud Billing (GCP), Cost Management (Azure): typically daily refresh
TAG DATA All resource tags + their values
USAGE METRICS CloudWatch / Monitoring / Insights: for recommendations (idle detection, right-sizing)
AUDIT/EVENT CloudTrail / Audit Logs / Activity Log: for activity-driven recommendationsEach of these is a separate set of API calls; the discovery process orchestrates them. The full list of API permissions required is documented at zop.dev/developer-docs/cloud-setup/permissions.
How ZopNight uses it
ZopNight’s discovery scheduler runs per-account discovery cycles independently. Account-level failures (one IAM permission missing in one child) do not block other accounts. The Discovery dashboard surfaces per-account status, last-successful-discovery timestamp, and any errors with remediation guidance.
2. Demo
A clean setup for an 8-account AWS estate:
SETUP TIMELINE:
Step 1: First account (about 5 min) - In ZopNight: Settings → Cloud Accounts → add an AWS account, method WIF-Assume Role, permission level read-only - Open the CloudFormation quick-create link while signed in to that AWS account; create the stack - Paste the role ARN from the stack outputs into ZopNight - ZopNight checks the role and reads the account number from AWS
Step 2: Remaining 7 accounts (a few minutes each) - Repeat step 1 in each account: one stack, one ZopNight cloud account - No management-account role, no StackSet
Step 3: First discovery cycle (a few minutes) - ZopNight begins discovery; one AssumeRoleWithWebIdentity call per account - Results: ~3,400 resources across the 8 accounts - Cost data backfill begins
TOTAL ELAPSED: under an hour from first stack to first dashboard.ONGOING: discovery refreshes every 6 hours, plus on change events and when you trigger it by hand; cost refreshes daily.When a new AWS account is later created, ZopNight does not find it on its own. Add it to your account-creation checklist: create the stack and connect it, and it is discovered straight away.
3. Hands-on (6 min)
For your cloud estate, plan the cross-account setup:
PROVIDER: __________ (AWS / GCP / Azure)ACCOUNT COUNT: _____CONNECTIONS NEEDED: _____ (one per AWS account / GCP project / Azure subscription, or one per Azure tenant)
CREDENTIAL STRATEGY: □ WIF-Assume Role per account (AWS, recommended) □ Static keys or temporary credentials (AWS) □ One-Click Connect per project (GCP, recommended) □ Service-account JSON key (GCP) □ Service principal or workload identity (Azure)
HOW YOU WILL CREATE EACH AWS ROLE: □ ZopNight's CloudFormation quick-create link, per account □ Your own IaC reproducing the same trust policy □ Manual (small estates only)
ESTIMATED SETUP TIME: _____ hours (Larger estates with multiple BUs may have political coordination overhead beyond the technical work)
CREDENTIAL ROTATION: Current rotation cadence: __________ Target cadence: __________ Migration to keyless methods (AWS role / GCP One-Click / Azure WIF)? __________If you’re using long-lived keys or service-principal secrets, plan the migration to keyless methods where the cloud offers one. The risk reduction is significant.
4. Knowledge check
Q1
For AWS, ZopNight’s recommended way to authenticate to each account is:
A. Direct IAM credentials stored separately in each child account individually
B. A single access key shared across every one of the member accounts in the organisation
C. Per-account hardcoded keys, entered by hand at onboarding for each account
D. A role in each account, assumed with a token for ZopNight’s Google identity
Show answer
Correct: D. Each account gets its own role, created by a CloudFormation stack, trusting ZopNight’s Google identity. ZopNight calls AssumeRoleWithWebIdentity and gets short-lived credentials each cycle. There is no management-account credential and no stored secret.
Q2
In ZopNight’s AWS role, what limits who can assume it?
A. The aud and sub conditions naming ZopNight’s identity
B. A tag condition requiring a ZopNight-owned principal tag
C. A source-IP condition listing ZopNight’s address ranges
D. Nothing; any AWS principal can assume the role
Show answer
Correct: A. The trust policy only accepts web-identity tokens whose aud and sub equal ZopNight’s Google service account, and ZopNight reads the account number from AWS’s own response rather than from the form.
Q3
GCP service-account JSON key vs One-Click Connect:
A. They are the same thing under two different names entirely
B. The JSON key is considerably easier to rotate automatically
C. The key is a secret you manage; One-Click is managed by ZopNight
D. The JSON key is the more secure of the two, being customer-managed
Show answer
Correct: C. The JSON key is a long-lived secret you hold and rotate. With One-Click Connect, ZopNight creates and manages its own service account in the project, so there is no key file for you to keep. One-Click is the recommended GCP method.
5. Apply
Connect each account in Settings → Cloud Accounts. The setup wizard walks through each method: the CloudFormation quick-create stack for an AWS role, the One-Click sign-in for a GCP project, and the service-principal fields for Azure.
After setup, monitor the Discovery dashboard for per-account success status. Any account showing repeated failures usually has a missing IAM permission: the dashboard surfaces the specific permission and remediation step.
Related lessons
- L1: Why multi-account
- L2: Cloud-provider hierarchies
- L4: Rollup vs isolation (next)
- L5: Multi-account anti-patterns
Glossary terms touched
Assume-role · Workload identity federation · Service principal