Outcome
By the end of this lesson, you will be able to configure the AWS IAM role for ZopNight and explain which permissions enable read-only discovery versus write execution.
| Prerequisites | L1 |
| Time | 10 minutes |
1. Concept
You do not give ZopNight a password or an access key. You create an IAM role in your AWS account, which is a named set of permissions, and you allow ZopNight to borrow it. AWS calls that assuming a role.
ZopNight runs on Google Cloud, so it borrows the role with its own Google identity. It presents a Google-signed identity token, and AWS exchanges that for short-lived role credentials (sts:AssumeRoleWithWebIdentity). ZopNight calls this method WIF-Assume Role, short for Workload Identity Federation, and it is the recommended way to connect. Nothing long-lived is stored. Static access keys and temporary STS credentials are also accepted, but the role is the method this lesson teaches.
You keep the role. You decide what is in it, and you can change or delete it at any time without involving anyone.
The read-only part
Finding resources, reading their usage, pulling the bill and producing recommendations all need permission to look and nothing more. ZopNight gives you a CloudFormation template that builds the role, and its read part is made of:
ReadOnlyAccess, the AWS-managed read-only policy, kept as a safety net for any read ZopNight has not listed explicitlyZopNightReadPolicyA,BandC, three managed policies that list every read action ZopNight uses, service by service (EC2, RDS, EKS, Lambda, S3, CloudWatch metrics, Cost Explorer, Resource Explorer and the rest)
Open any of them in the IAM console and read the verbs. They are Describe, Get, List and similar read actions. None of them changes anything.
Deploy only this and you get the full picture: every resource found, every report, every recommendation. What you do not get is anything happening. No schedules, no automatic fixes. This is what “monitor mode” means, and it is a perfectly reasonable place to stop.
The parts that can change something
If you want schedules and fixes, you choose the read_write permission level when you launch the stack (the template’s PermissionLevel parameter is read_only or read_write). That adds two more managed policies to the role:
ZopNightWritePolicy: the actions schedules and scaling need, such asec2:StartInstances,ec2:StopInstancesand the Auto Scaling and Application Auto Scaling policy callsZopNightRemediationPolicy: the actions a remediation needs, such asec2:DeleteVolumefor an orphaned volume
If you start read-only, a separate upgrade template attaches the same write policies to your existing role later.
ZopNight’s write policies apply to "Resource": "*" and carry no Condition block. If you want AWS itself to refuse anything outside dev, test and stage, add your own Deny statement to the role. An extra Allow with a condition would not restrict anything, because the write policy already allows these actions on every resource. For example:
{ "Sid": "DenyStartStopOutsideNonProd", "Effect": "Deny", "Action": ["ec2:StartInstances", "ec2:StopInstances"], "Resource": "*", "Condition": { "StringNotEquals": {"aws:ResourceTag/environment": ["dev", "test", "stage"]} }}That is worth dwelling on. With a statement like this in place, if somebody sets up a ZopNight schedule badly and it tries to stop a production machine, AWS refuses the request. Instances with no environment tag are refused too. The protection lives in your account, not in ours. It is your addition, though: ZopNight does not ship it, so check that it matches how your resources are actually tagged.
Anything ZopNight asks for passes through AWS’s own permission check before it reaches a resource.
Saying who may borrow the role
The role also carries a short document naming who is allowed to assume it. For ZopNight it trusts Google as an identity provider, and only one Google identity, ZopNight’s own:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<your-account-id>:oidc-provider/accounts.google.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "accounts.google.com:aud": "<ZopNight service account ID>", "accounts.google.com:sub": "<ZopNight service account ID>" } } }]}The role trusts one federated identity provider, accounts.google.com, and the condition pins it to ZopNight’s Google service account: a token from any other Google identity is refused by AWS. The CloudFormation stack also registers the accounts.google.com identity provider in your account if it is not there yet.
When you connect, ZopNight works out which AWS account it reached from what AWS itself reports back, not from anything typed into the form.
Why it is not simply read-only
A purely read-only role means no schedules, no automatic fixes, no scaling changes. That is a reporting tool, and reporting is the thing you already have.
So the honest description is read-mostly. Reading is the floor. Every ability to change something sits above it, and only you add it.
Many customers connect an account as read_only first and switch it to read_write later, once they are comfortable with what the product does. That order is deliberate: you see the findings before you allow any change.
The level is enforced by ZopNight’s servers every time an action runs, not just by hiding buttons. If someone tries to stop an instance on a read_only account, ZopNight refuses before any call reaches AWS. Discovery and recommendations still work at read_only. Actions that change your cloud are held back, and so is attaching the account’s resources to a schedule, because a schedule exists to change them. When you change the level, running schedules pick it up without a restart.
When you have many AWS accounts
Large companies run an AWS Organization with dozens or hundreds of accounts under it. ZopNight connects them one at a time:
- Each AWS account gets its own copy of the CloudFormation stack and its own role
- Each one is then added in ZopNight as its own cloud account, under your one ZopNight organisation
- There is no StackSet template and no organisation-wide rollout from ZopNight; if you use your own automation to launch the stack in many accounts, you still add each account in ZopNight
2. Demo
A typical AWS connection walkthrough:
T+0 Customer opens ZopNight → Cloud Accounts → Add AWS AccountT+1 min ZopNight displays the IAM trust policy + permissions templateT+1 min Customer copies the CloudFormation template URLT+2 min Customer launches in AWS CloudFormation ConsoleT+3 min Stack creates the IAM roleT+4 min Customer pastes the role ARN (a stack output) back to ZopNightT+4 min ZopNight validates via STS AssumeRoleWithWebIdentityT+5 min Account marked Active; discovery preview beginsFive minutes from start to active. The CloudFormation template eliminates manual IAM policy editing.
3. Hands-on (6 min)
Connect an AWS account (or audit one already connected):
1. In ZopNight, navigate to Cloud Accounts → Add AWS Account.2. Note the offered CloudFormation template URL.3. In AWS Console (a sandbox account, not production), launch the stack.4. Inspect the IAM role created. Verify: - The read policies hold only read actions (the write policies appear only if you chose read_write) - The trust policy names accounts.google.com and sts:AssumeRoleWithWebIdentity5. Paste the role ARN back to ZopNight; verify connection in <60 seconds.6. After connection, open Permission Visibility (covered in L4) and confirm Granted across the expected service categories.4. Knowledge check
Q1
The AWS IAM role for ZopNight discovery is described as “read-mostly” because:
A. The baseline is read-only across all services needed for discovery, metrics, billing, and recommendations
B. It uses an old API
C. It only has around 50% of the permissions that it actually needs in order to function correctly
D. It can only read every other request
Show answer
Correct: A. Writes (StartInstances, StopInstances, DeleteVolume and so on) come only with the read_write permission level, which the customer chooses. Read-mostly = read-only baseline + writes the customer opts into.
Q2
How does ZopNight’s recommended AWS connection prove to AWS that it may assume your role?
A. It sends a long-lived IAM user access key that you created and pasted into ZopNight
B. It signs every request with a client certificate that your own AWS private CA issued to ZopNight
C. It presents a Google-signed token, and the trust policy accepts only ZopNight’s own Google identity
D. It logs in to the AWS console with an IAM user and password stored in the vault
Show answer
Correct: C. The role trusts accounts.google.com and allows sts:AssumeRoleWithWebIdentity only when the token’s audience and subject are ZopNight’s Google service account. There is no long-lived secret.
Q3
A team wants ZopNight to schedule EC2 instances tagged environment=dev but never anything tagged environment=prod. The defensible IAM configuration:
A. Add a Deny on ec2:StartInstances and ec2:StopInstances when aws:ResourceTag/environment is not in [“dev”, “test”, “stage”]
B. Don’t grant EC2 start/stop permissions
C. Rely on ZopNight never requesting anything in production, since the product does not target production resources by default
D. Use a separate AWS account for dev
Show answer
Correct: A. ZopNight’s own write policy has no tag condition and already allows these actions on every resource, so the restriction has to be a Deny that you add to the role. Once it is there, AWS refuses any request on a resource not tagged dev, test or stage (untagged ones included) before it reaches the instance. The defense is at the cloud provider’s policy layer, not the application layer, so even a buggy call cannot stop a prod instance.
5. Apply
ZopNight publishes the current policy and the CloudFormation template at:
- Cloud Accounts → Add AWS Account in the product
- Documentation for offline review
For organizations with many AWS accounts: launch the stack once per account (with your own automation if you like), then add each account in ZopNight.
Related lessons
- L3: GCP & Azure credentials (next)
- L4: Permission Visibility
- T2.M2.5: Adopt-or-replace existing cloud scaling
Glossary terms touched
IAM role · Assume-role · Workload identity federation