Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/
5 changes: 5 additions & 0 deletions templates/iacm-remediation/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "IaCM Remediation",
"description": "AI-powered agent that automatically remediates infrastructure issues identified by Harness IaCM, STO, and CCM modules. It analyzes the issue, updates the source code in Terraform/OpenTofu repositories, and raises a pull request for review.",
"version": "1.0.0"
}
140 changes: 140 additions & 0 deletions templates/iacm-remediation/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
pipeline:
stages:
- steps:
- name: init
iacm:
uses: [email protected]
with:
command: init
- name: plan
iacm:
uses: [email protected]
with:
command: plan
- name: iacm_remediation_agent
id: remediate
run:
container:
connector: account.harnessImage
image: pkg.harness.io/vrvdt5ius7uwygso8s0bia/harness-agents/iacm-remediation-agent-plugin:IAC-5536-iacm-remediation-agent
with:
ROOT_DIR: <+iacmOutput.rootDir>
env:
ANTHROPIC_API_KEY: <+inputs.llmConnector.token>
PLUGIN_REMEDIATION_TYPE: <+inputs.remediationType>
PLUGIN_RECOMMENDATION: <+inputs.recommendation>
- name: show_git_diff
id: git_diff
run:
shell: bash
script: |-
cd <+iacmOutput.rootDir>
git add -A
git diff --cached
- name: fix_env_variables
id: fix_env_variables
run:
shell: bash
script: |-
set -euo pipefail

# Debug: show raw iacmOutput values
echo "=== Raw iacmOutput values ==="
echo "REPO_TYPE: '$REPO_TYPE'"
echo "REPO_URL: '$REPO_URL'"
echo "REPO_TOKEN: (length=${#REPO_TOKEN})"
echo "ROOT_DIR: '$ROOT_DIR'"
echo "==="

# Derive SCM provider from iacmOutput.repoType (e.g. Github, Bitbucket, Gitlab)
SCM_PROVIDER=$(echo "$REPO_TYPE" | tr '[:upper:]' '[:lower:]')
echo "SCM Provider: $SCM_PROVIDER"

# Extract netrc machine from repo URL (e.g. github.com)
NETRC_MACHINE=$(echo "$REPO_URL" | sed -E 's|https?://([^/]+)/.*|\1|')
NETRC_USERNAME=$(echo "$REPO_URL" | sed -E 's|https?://[^/]+/([^/]+)/.*|\1|')

# Extract base URL (protocol + host)
BASE_URL=$(echo "$REPO_URL" | sed -E 's|(https?://[^/]+).*|\1|')

# Extract repo path (owner/repo) from actual git remote, stripping .git suffix
ACTUAL_URL=$(cd "$ROOT_DIR" && git remote get-url origin)
REPO=$(echo "$ACTUAL_URL" | sed -E 's|https?://[^/]+/||; s|\.git$||')

cd "$ROOT_DIR"

# Get branch from the cloned repo
SOURCE_BRANCH=$(git rev-parse --abbrev-ref HEAD)

echo "Repo: $REPO, Branch: $SOURCE_BRANCH"

# Set up git authentication by embedding token in remote URL
CURRENT_URL=$(git remote get-url origin)
AUTH_URL=$(echo "$CURRENT_URL" | sed -E "s|https://|https://x-access-token:${REPO_TOKEN}@|")
git remote set-url origin "$AUTH_URL"

echo "SCM_PROVIDER=$SCM_PROVIDER" >> $DRONE_OUTPUT
echo "TOKEN=$REPO_TOKEN" >> $HARNESS_OUTPUT_SECRET_FILE
echo "NETRC_MACHINE=$NETRC_MACHINE" >> $DRONE_OUTPUT
echo "NETRC_USERNAME=$NETRC_USERNAME" >> $DRONE_OUTPUT
echo "NETRC_PASSWORD=$REPO_TOKEN" >> $HARNESS_OUTPUT_SECRET_FILE
echo "BASE_URL=$BASE_URL" >> $DRONE_OUTPUT
echo "REPO=$REPO" >> $DRONE_OUTPUT
echo "SOURCE_BRANCH=$SOURCE_BRANCH" >> $DRONE_OUTPUT
echo "WORKING_DIR=$(pwd)" >> $DRONE_OUTPUT
env:
REPO_TOKEN: <+iacmOutput.repoToken>
REPO_URL: <+iacmOutput.repoUrl>
REPO_TYPE: <+iacmOutput.repoType>
ROOT_DIR: <+iacmOutput.rootDir>
- name: push_and_create_pr
id: push_and_create_pr
run:
container:
image: pkg.harness.io/vrvdt5ius7uwygso8s0bia/harness-agents/create-pr-plugin:IAC-5536-iacm-remediation-agent
connector: account.harnessImage
env:
PLUGIN_SCM_PROVIDER: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.SCM_PROVIDER>
PLUGIN_TOKEN: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.TOKEN>
PLUGIN_REPO: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.REPO>
PLUGIN_SOURCE_BRANCH: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.SOURCE_BRANCH>
PLUGIN_WORKING_DIR: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.WORKING_DIR>
PLUGIN_NETRC_MACHINE: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.NETRC_MACHINE>
PLUGIN_NETRC_USERNAME: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.NETRC_USERNAME>
PLUGIN_NETRC_PASSWORD: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.NETRC_PASSWORD>
PLUGIN_BRANCH_SUFFIX: iacm-drift-remediation
PLUGIN_UNIQUE_PER_EXECUTION: "true"
PLUGIN_FORCE_PUSH: "true"
PLUGIN_COMMIT_MESSAGE: "IaCM drift remediation: automated changes by Harness AI"
PLUGIN_PUSH_CHANGES: "true"
PLUGIN_CREATE_PR: "true"
PLUGIN_PR_TITLE: "IaCM Drift Remediation: Automated changes by Harness AI"
PLUGIN_PR_DESCRIPTION: Automated infrastructure drift remediation for Terraform/OpenTofu. The source code has been updated to match the actual infrastructure state. Please review the changes before merging.
PLUGIN_IS_DRAFT: "false"
PLUGIN_BYPASS_RULES: "false"
PLUGIN_HARNESS_ACCOUNT_ID: <+env.HARNESS_ACCOUNT_ID>
PLUGIN_HARNESS_ORG_ID: <+env.HARNESS_ORG_ID>
PLUGIN_HARNESS_PROJECT_ID: <+env.HARNESS_PROJECT_ID>
PLUGIN_HARNESS_BASE_URL: <+pipeline.stages.iac_1.steps.fix_env_variables.output.outputVariables.BASE_URL>
PLUGIN_DEBUG: "false"
PLUGIN_OUTPUT_FILE: <+env.DRONE_OUTPUT>
name: iac
timeout: 10m
workspace: <+inputs.workspace>
inputs:
llmConnector:
type: connector
description: Anthropic API connector for Claude AI
workspace:
type: string
description: IaCM workspace identifier
remediationType:
type: string
default: iacm-drift
description: Type of remediation (iacm-drift, sto, cloud-cost)
recommendation:
type: string
description: JSON string with recommendation details (required for sto and cloud-cost types)
harnessKey:
type: secret
default: harness_api_key
161 changes: 161 additions & 0 deletions templates/iacm-remediation/wiki.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# IaCM Remediation Agent

**Version:** 1.0.0
**Name:** IaCM Remediation

## Overview

The **IaCM Remediation Agent** is an AI-powered agent that automatically remediates infrastructure issues identified by Harness IaCM, STO, and CCM modules. It analyzes the issue, updates the source code in Terraform/OpenTofu repositories, and raises a pull request for review.

Supported remediation types:
- **iacm-drift**: Resolves infrastructure drift by updating source code to match the actual infrastructure state.
- **sto**: Fixes security vulnerabilities identified by Harness STO scans.
- **cloud-cost**: Applies cost optimization recommendations from Harness CCM.

---

## Key capabilities

- **Automatic drift detection**: Uses IaCM workspace configuration to run Terraform/OpenTofu `init` and `plan` commands and detect infrastructure drift automatically.

- **AI-powered code fixes**: Analyzes plan output to understand resource changes and updates `.tf` files to reflect actual infrastructure state with minimal, targeted changes.

- **Multi-type remediation**: Supports infrastructure drift remediation (`iacm-drift`), security vulnerability fixes (`sto`), and cloud cost optimization (`cloud-cost`).

- **Pull request automation**: Creates PRs with clear descriptions, submits for human review before any merge, and respects branch protection rules.

- **Context-aware reasoning**: Uses tfvar files and workspace variables for additional context, understands Terraform resource relationships and dependencies.

---

## How it works

1. **Init**: Runs `terraform/tofu init` using the IaCM workspace configuration.
2. **Plan**: Executes `terraform/tofu plan` to detect drift or changes.
3. **Remediation agent**: Analyzes the plan output and applies targeted code changes to resolve the issue.
4. **Show changes**: Displays `git diff` of applied fixes.
5. **Detect SCM and configure auth**: Derives repository information and credentials from the IaCM workspace (repo URL, token, branch, SCM provider).
6. **Push and create PR**: Commits changes, pushes to a new branch, and creates a pull request back to the source branch.

---

## Inputs

| Input | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `llmConnector` | connector | Yes | - | Anthropic API connector for Claude AI |
| `workspace` | string | Yes | - | IaCM workspace identifier |
| `remediationType` | string | No | `iacm-drift` | Type of remediation: `iacm-drift`, `sto`, or `cloud-cost` |
| `recommendation` | string | No | - | JSON string with recommendation details (required for `sto` and `cloud-cost` types) |
| `harnessKey` | secret | No | `harness_api_key` | Harness API key for authentication |

---

## Configuration

- **Platform**: Linux (arm64)
- **Timeout**: 10 minutes
- **Max iterations**: 200 (for coding agent)
- **Branch suffix**: `iacm-drift-remediation`
- **Force push**: Enabled
- **Unique per execution**: Yes (adds timestamp suffix)

---

## Usage example

### Basic usage (IaCM drift remediation)

```yaml
inputs:
llmConnector: <select Anthropic connector>
workspace: "my-workspace-id"
```

### STO remediation

```yaml
inputs:
llmConnector: <select Anthropic connector>
workspace: "my-workspace-id"
remediationType: "sto"
recommendation: '{"vulnerability": "CVE-2024-1234", "severity": "high", "fix": "upgrade package X to version Y"}'
```

### Cloud cost optimization

```yaml
inputs:
llmConnector: <select Anthropic connector>
workspace: "my-workspace-id"
remediationType: "cloud-cost"
recommendation: '{"resource": "aws_instance.web", "suggestion": "downsize from m5.xlarge to m5.large"}'
```

---

## Technical details

### IaCM remediation agent plugin
- **Container image**: `pkg.harness.io/.../iacm-remediation-agent-plugin`
- **Working directory**: Derived from `<+iacmOutput.rootDir>`
- **Inputs**: `ROOT_DIR`, `ANTHROPIC_API_KEY`, `PLUGIN_REMEDIATION_TYPE`, `PLUGIN_RECOMMENDATION`

### Create PR plugin
- **Container image**: `pkg.harness.io/.../create-pr-plugin`
- **Working directory**: Set via `PLUGIN_WORKING_DIR` (derived from IaCM workspace root)
- **Commit message**: "IaCM drift remediation: automated changes by Harness AI"

### Branch management
- **Branch name**: `<source-branch>-iacm-drift-remediation-<timestamp>`
- **Unique per execution**: Yes
- **Force push**: Enabled

### Pull request configuration
- **Auto-create**: Yes
- **PR title**: "IaCM Drift Remediation: Automated changes by Harness AI"
- **Draft mode**: Disabled
- **Bypass rules**: Disabled (respects branch protection rules)

### SCM provider support

Repository information (URL, token, branch, SCM type) is automatically derived from the IaCM workspace configuration. Supported providers:
- **GitHub**
- **GitLab**
- **Bitbucket**
- **Harness Code**

---

## Troubleshooting

### Init or plan fails
- Verify the IaCM workspace is correctly configured with valid provider credentials.
- Check that the workspace points to a valid Terraform/OpenTofu repository.

### Agent doesn't generate fixes
- Verify the `llmConnector` is properly configured with valid Anthropic credentials.
- Ensure the plan step detected changes.
- Check agent logs for error details.

### PR creation fails with "Not Found"
- Verify the repository information is correctly derived from the workspace.
- Check that the token has push and PR creation permissions.

### Authentication errors on git push
- The agent sets up authentication by embedding the workspace token in the git remote URL.
- Verify the workspace token has write access to the repository.

---

## Security considerations

- API keys are stored as Harness secrets and never exposed in logs.
- Agent only applies targeted fixes based on plan analysis.
- All changes are submitted via PR for human review.
- No automatic merging — requires developer approval.
- Respects branch protection rules (bypass disabled by default).

---

**Last updated:** March 2026
Loading