跳到正文
DEV Community· Vitaliy Dmitriev·· 2 小時前AI 評分60

我讓 AI 智能體處理 Terraform 任務,它發現憑證問題

I gave an AI agent a Terraform task. It found a credentials problem.

AI 導讀

作者讓 AI 智能體處理 Terraform 基建任務時,智能體發現預期的 AWS profile 不可用,進一步查出自動化工作共用長期有效的管理員金鑰,於是停止並報告問題。

正文

I gave an AI agent a Terraform task. It found a credentials problem.

Part 1 of 3 in "Terraform with an AI co-worker: access, testing, review".

The ticket was ordinary: create an S3 bucket, two SQS queues and an IAM user across five environments, using the existing Terraform setup.

I gave it to an AI agent. It prepared the code and ran its checks, but deployment hit a problem. The AWS profiles Terraform expected weren't available on the machine. Investigating those profiles led to something more interesting than the ticket itself: permanent administrator keys shared with automated jobs.

The agent stopped and reported the problem. It didn't ask me to paste the keys into the chat or start replacing credentials that other workloads depended on.

That pause was probably the most useful part of this stage of the work.

This series follows the same Terraform task through three stages: sorting out access, testing the change, and reviewing the work. This first part is about the credentials the agent could use and what we could verify before allowing a deployment.

The profiles were familiar. The credentials behind them were less reassuring.

Our Terraform configuration expected one AWS profile per environment, with names like stage-user-terraform and prd-user-terraform. Each pointed to an IAM user with long-lived access keys and administrator permissions. The Terraform state was stored in S3 in the AWS organization's management account.

The keys weren't on the agent's machine. Using read-only queries, it found that the existing keys had been used that day by automated data jobs. In two environments, the users already had two keys each, which is the AWS limit per IAM user.

Creating another key for those users would first require deleting one. That would turn a small infrastructure ticket into a credential rotation for workloads outside its scope.

There were several tempting shortcuts: copy an existing secret from wherever it was stored, replace a key to make room, or use a more privileged identity because it happened to work. None belonged in this task.

Also, AWS doesn't let you retrieve an existing secret access key after creation. Inspecting key metadata and usage is different from having the credential itself.

The rules helped. They didn't remove the permissions.

The agent had standing instructions:

  • Read-only investigation was pre-approved; important changes needed human approval.
  • It was not to delete or modify resources it hadn't created without explicit authorization.
  • Missing credentials and ambiguous ownership were reasons to stop and ask.
  • A refused operation was not permission to find another way around the refusal.

These rules explain the behavior I wanted. They don't make an administrator role read-only.

That distinction matters here because the SSO role we eventually used still had administrator permissions. We improved credential handling, but the agent's restraint and the approval workflow remained part of the boundary. A dedicated role with narrower permissions is the next step.

There was also a small local example. A Terraform run left a generated file in the repository, and the safety layer blocked the agent's attempt to delete it. The agent moved it into a holding directory and reported the location, leaving final deletion to me.

That preserved the file, but I wouldn't present it as proof that the guardrail worked perfectly. Moving a file also changes the working tree. Whether that is an acceptable alternative depends on what the restriction is meant to protect. The useful detail was that the agent reported the alternative instead of silently removing the file another way.

Keep the profile names, change how we authenticate

The agent proposed four options. We chose one that left the Terraform code and the shared keys alone: keep the expected profile names, but resolve them through personal AWS IAM Identity Center logins, commonly called AWS SSO.

Those logins provide temporary role credentials instead of another permanent key. We put the profiles in a separate AWS config file, selected explicitly when running Terraform.

Here is an illustrative version, with placeholders:

# ~/.aws/config-terraform
# Profile configuration only, no secret access keys.
[sso-session company]
sso_start_url = https://<your-sso-portal>/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access

[profile stage-user-terraform]
sso_session = company
sso_account_id = <stage-account-id>
sso_role_name = <your-permission-set>
region = us-east-1

# Existing backend profile name; this is NOT the AWS root user.
[profile root-user-terraform]
sso_session = company
sso_account_id = <management-account-id>
sso_role_name = <your-permission-set>
region = us-east-1

The root-user-terraform name is unfortunate, but it was already what the backend expected. Here it refers to an SSO role in the management account, not root credentials.

We logged in with the separate configuration and selected it inside a subshell for the Terraform commands. An investigation command looks like this:

AWS_CONFIG_FILE="$HOME/.aws/config-terraform" \
  aws sso login --sso-session company

(
  export AWS_CONFIG_FILE="$HOME/.aws/config-terraform"
  export AWS_PROFILE=root-user-terraform
  cd infra || exit 1
  terraform workspace select stage || exit 1
  terraform plan -lock=false -target=module.my-change
)

The paths, workspace and module address are examples. This assumes an initialized backend and an AWS provider configuration that explicitly selects the environment profile. The backend and provider authenticate separately; setting AWS_PROFILE alone doesn't separate their access.

The two plan flags also need context. We used -lock=false during the investigation to avoid a remote lock write, and targeting to inspect the ticket's scope. These are not defaults I'd use for deployment. An unlocked plan can become stale if another operation changes the state, and targeting can omit changes outside the selected dependency graph.

The separate config file reduces accidental profile use, and the subshell keeps these environment settings from remaining in my interactive shell. Neither prevents a process with access to the file and cached SSO session from selecting the profile again. Exiting the subshell doesn't revoke the session.

Before using this pattern, check credential sources and precedence too. Existing environment credentials or static credentials under the same profile names can interfere with the intended login. The Terraform S3 backend and the AWS provider also need versions that support your SSO configuration.

So what did we actually improve? We avoided distributing another long-lived secret, left the pipeline credentials untouched, and used personal role sessions with better attribution than a shared IAM user. The remaining admin permissions still deserved attention.

Could it write the state? We gathered evidence without trying a write.

Reading infrastructure was only part of the access question. An eventual apply also needed permission to update the state in the management account and use the configured locking mechanism.

We kept this investigation read-only:

  1. Run a Terraform plan with locking disabled for each environment we could authenticate to. This checked state reads and the AWS reads needed by that plan.
  2. Inspect the state bucket's policy. There was no bucket policy.
  3. Use the IAM policy simulator to evaluate the relevant S3 actions against the bucket and object resources. The simulated result was allowed.

The plan demonstrated that the reads it actually performed worked. The simulation supplied evidence for write permissions, but it wasn't an end-to-end write test. No bucket policy also doesn't, by itself, mean writes are allowed.

AWS documents limitations in the simulator, including resource-policy simulation for IAM roles and differences from live request evaluation. A result depends on the policies and context being evaluated. I wouldn't turn allowed into a promise that the eventual apply will succeed.

An independent reviewer agent rechecked the evidence and inspected encryption and organization controls. The reported bucket encryption didn't require a customer-managed KMS key. It also confirmed that SCPs don't restrict identities in the management account. That last point makes the account more sensitive, not less.

Locking permissions need their own check. S3 lock files require object permissions on the lock path; a DynamoDB-backed lock needs the relevant table permissions instead. An unlocked plan doesn't exercise either.

Two environments had expired SSO logins and weren't checked. We reported them as unverified rather than extending the result from the other environments.

Access wasn't the only thing blocking an apply

The real plan also exposed a mismatch between the shared Terraform configuration and the deployed environments. A full apply in three test environments would have included other teams' changes and deleted existing storage objects, well outside this ticket.

We chose a targeted deployment approach for this change and left the broader reconciliation as separate work. That didn't make the plan automatically safe: -target can include dependencies and leave other changes unapplied. I'll return to the plan's scope and the testing in Part 2.

Getting the right credentials was necessary. It wasn't permission to apply everything those credentials could reach.

What this changed for me

The agent prepared the change and investigated the access problem. A person still runs the apply.

We didn't rotate shared keys, create another administrator key or change the Terraform code just to get past the missing profiles. We found a way to use temporary personal credentials, while being explicit that those credentials still carried too much power for a narrowly scoped task.

For a team starting with AI-assisted infrastructure work, that is a useful first question: what identity will the agent use, and what can that identity actually do?

In this case, the missing login exposed an access arrangement worth revisiting. I would rather get that finding before deployment than discover the dependency on shared admin keys halfway through replacing one.


This is Part 1 of "Terraform with an AI co-worker: access, testing, review".

  • Part 2 will cover testing: using a temporary bucket and a real upload to check the change, cleaning up the test resources, and handling the unrelated changes in the plan.
  • Part 3 will cover review: what independent AI reviewers checked, what they caught, and which conclusions still needed human judgement.

Technical references

來源:DEV Community · dev.to