Back to list
refractionPOINT

limacharlie-iac

by refractionPOINT

LimaCharlie AI Capabilities

3🍴 1📅 Jan 23, 2026

SKILL.md


name: limacharlie-iac description: | Manage LimaCharlie Infrastructure as Code using ext-git-sync compatible repository structure. Initialize IaC repos, add/remove tenants, manage global and tenant-specific configurations (D&R rules, outputs, FIM, extensions, etc.), and coordinate with ext-git-sync for deployment. Supports importing existing rules from tenants and promoting tenant rules to global. Use when setting up multi-tenant config management, adding orgs to IaC, or managing detection rules across organizations via git. allowed-tools:

  • Task
  • Read
  • Write
  • Edit
  • Bash
  • Glob
  • Grep
  • Skill
  • AskUserQuestion

LimaCharlie Infrastructure as Code Manager

Manage multi-tenant LimaCharlie configurations using git-based Infrastructure as Code, compatible with the ext-git-sync extension.


LimaCharlie Integration

Prerequisites: Run /init-lc to initialize LimaCharlie context.

API Access Pattern

All LimaCharlie API calls go through the limacharlie-api-executor sub-agent:

Task(
  subagent_type="lc-essentials:limacharlie-api-executor",
  model="sonnet",
  prompt="Execute LimaCharlie API call:
    - Function: <function-name>
    - Parameters: {<params>}
    - Return: RAW | <extraction instructions>
    - Script path: {skill_base_directory}/../../scripts/analyze-lc-result.sh"
)

Critical Rules

RuleWrongRight
MCP AccessCall mcp__* directlyUse limacharlie-api-executor sub-agent
D&R RulesWrite YAML manuallyUse generate_dr_rule_*() + validate_dr_rule_components()
OIDUse org nameUse UUID (call list_user_orgs if needed)

Overview

This skill helps you manage LimaCharlie organizations using Infrastructure as Code:

┌─────────────────────────────────────────────────────────────────┐
│  IaC REPOSITORY (ext-git-sync compatible)                       │
│                                                                 │
│  org-manifest.yaml        ← Friendly name → OID mapping         │
│                                                                 │
│  hives/                   ← GLOBAL configs (all tenants)        │
│  ├── dr-general.yaml         D&R rules                          │
│  ├── fp.yaml                 False positives                    │
│  ├── outputs.yaml            Output destinations                │
│  ├── extensions.yaml         Extensions to enable               │
│  ├── integrity.yaml          FIM rules                          │
│  └── ...                                                        │
│                                                                 │
│  orgs/                    ← PER-TENANT configs                  │
│  ├── <oid-1>/                                                   │
│  │   ├── index.yaml          Includes global + custom           │
│  │   └── custom/             Tenant-specific overrides          │
│  │       ├── rules.yaml                                         │
│  │       └── fim.yaml                                           │
│  └── <oid-2>/                                                   │
│      └── index.yaml                                             │
│                                                                 │
│  exports/                 ← Auto-generated by ext-git-sync      │
│  └── orgs/...                                                   │
└─────────────────────────────────────────────────────────────────┘

Key Concepts

ext-git-sync Compatibility

This skill generates repositories compatible with LimaCharlie's ext-git-sync extension:

  • Folder names under orgs/ are OIDs (required by ext-git-sync)
  • Each org has an index.yaml that includes global and custom configs
  • Global configs in hives/ are shared via relative path includes

Friendly Name Mapping

Since OID folders are hard to read, the skill maintains org-manifest.yaml:

version: 1
orgs:
  acme-corp:
    oid: 7e41e07b-c44c-43a3-b78d-41f34204789d
    description: "Acme Corporation - Production"
    added: "2025-11-30"

  globex:
    oid: a326700d-3cd7-49d1-ad08-20b396d8549d
    description: "Globex Industries"
    added: "2025-11-30"

You refer to orgs by friendly name; the skill translates to OIDs.


Commands

Initialize Repository

"Set up a new IaC repo" or "Initialize LimaCharlie IaC at /path/to/repo"

Creates a new ext-git-sync compatible repository:

<repo-path>/
├── org-manifest.yaml
├── hives/
│   ├── dr-general.yaml
│   ├── fp.yaml
│   ├── outputs.yaml
│   ├── extensions.yaml
│   ├── integrity.yaml
│   ├── artifact.yaml
│   ├── exfil.yaml
│   ├── resources.yaml
│   └── installation_keys.yaml
├── orgs/
│   └── .gitkeep
├── exports/
│   └── .gitkeep
├── README.md
└── .gitignore

Workflow:

  1. Create directory structure
  2. Initialize global config files with version: 3 headers
  3. Create empty org-manifest.yaml
  4. Initialize git repository
  5. Provide instructions for ext-git-sync setup

Add Existing Tenant

"Add tenant acme-corp" or "Add org Acme Corporation to IaC"

Adds an existing LimaCharlie organization to the repository:

Workflow:

  1. Look up organization by name using list_user_orgs
  2. Confirm with user if multiple matches
  3. Create orgs/<oid>/index.yaml with global includes
  4. Create orgs/<oid>/custom/ directory for future customizations
  5. Add entry to org-manifest.yaml
  6. Optionally: Export current config from LC using ext-git-sync or limacharlie configs fetch
  7. Commit changes

Example index.yaml generated:

version: 3
include:
  # Global configurations
  - ../../hives/extensions.yaml
  - ../../hives/dr-general.yaml
  - ../../hives/fp.yaml
  - ../../hives/outputs.yaml
  - ../../hives/integrity.yaml
  - ../../hives/artifact.yaml
  - ../../hives/exfil.yaml
  - ../../hives/resources.yaml
  - ../../hives/installation_keys.yaml
  # Custom configurations for this org (uncomment as needed)
  # - custom/rules.yaml
  # - custom/fim.yaml
  # - custom/outputs.yaml

Create New Organization

"Create new org called acme-corp" or "Create tenant Acme Corporation in US region"

Creates a new organization in LimaCharlie AND adds it to the repository:

Workflow:

  1. Use create_org to create organization in LC
  2. Follow "Add Existing Tenant" workflow
  3. Provide installation key information

Remove Tenant from IaC

"Remove acme-corp from IaC" (does NOT delete the org in LC)

Workflow:

  1. Look up OID from org-manifest.yaml
  2. Remove orgs/<oid>/ directory
  3. Remove entry from org-manifest.yaml
  4. Commit changes

Rule Management

Add Global Rule (New)

"Add detection for encoded PowerShell to all tenants" "Create global rule to detect mimikatz"

Creates a NEW rule and adds it to global config:

Workflow:

  1. Use AI generation (generate_dr_rule_detection, generate_dr_rule_respond)
  2. Validate with validate_dr_rule_components
  3. Append to hives/dr-general.yaml
  4. Commit with descriptive message

Import Rule from Tenant

"Import rule encoded-powershell from acme-corp" "Get rule mimikatz-detection from globex into IaC"

Fetches an EXISTING rule from a LimaCharlie tenant and adds it to the IaC repo:

Workflow:

  1. Look up tenant OID from org-manifest.yaml
  2. Fetch rule using get_dr_general_rule API:
    Function: get_dr_general_rule
    Parameters:
      oid: "<tenant-oid>"
      rule_name: "encoded-powershell"
    
  3. Ask user: Add as global (all tenants) or tenant-specific?
  4. If global: Add to hives/dr-general.yaml
  5. If tenant-specific: Add to orgs/<oid>/custom/rules.yaml
  6. Commit changes

Promote Rule to Global

"Promote rule encoded-powershell from acme-corp to global" "Make rule X from globex apply to all tenants"

Takes an existing rule from ONE tenant and makes it apply to ALL tenants:

Workflow:

  1. Look up source tenant OID from org-manifest.yaml
  2. Fetch rule using get_dr_general_rule API
  3. Add rule to hives/dr-general.yaml
  4. Ask user: Remove from tenant's custom config? (if it was tenant-specific)
  5. If yes: Remove from orgs/<oid>/custom/rules.yaml
  6. Commit: "Promote rule [name] from [tenant] to global"

Example:

User: "Promote rule lateral-movement-psexec from acme-corp to global"

Skill:
1. Fetches rule from acme-corp (OID: 7e41e07b-...)
2. Adds to hives/dr-general.yaml:

   hives:
     dr-general:
       lateral-movement-psexec:
         data:
           detect: ...
           respond: ...
         usr_mtd:
           enabled: true

3. All tenants now get this rule via their index.yaml includes

Copy Rule Between Tenants

"Copy rule X from acme-corp to globex" "Give globex the same custom-detection rule that acme-corp has"

Copies a rule from one tenant to another (without making it global):

Workflow:

  1. Look up source tenant OID
  2. Fetch rule from source tenant
  3. Look up destination tenant OID
  4. Add to orgs/<dest-oid>/custom/rules.yaml
  5. Update destination's index.yaml to include custom rules if needed
  6. Commit changes

Add Tenant-Specific Rule

"Add custom detection only for acme-corp" "Create rule for globex to detect their specific app"

Creates a NEW rule for ONE tenant only:

Workflow:

  1. Look up tenant OID from org-manifest.yaml
  2. Use AI generation for rule
  3. Validate rule
  4. Create/update orgs/<oid>/custom/rules.yaml
  5. Update orgs/<oid>/index.yaml to include custom rules
  6. Commit changes

List Rules

"Show all global rules" "What rules does acme-corp have?" "List custom rules for globex"

Displays rules from the IaC repo:

Global Rules (hives/dr-general.yaml)
════════════════════════════════════
- encoded-powershell-execution    (enabled)
- mimikatz-command-line           (enabled)
- lateral-movement-psexec         (enabled)

Tenant: acme-corp (7e41e07b-...)
Custom Rules (orgs/.../custom/rules.yaml)
─────────────────────────────────────────
- acme-specific-app-detection     (enabled)

Tenant: globex (a326700d-...)
Custom Rules: (none)

Configuration Management

Add Global Configuration

"Add global output to send detections to Slack" "Enable Zeek extension for all orgs" "Add FIM rule to watch /etc/passwd globally"

Adds configuration that applies to ALL tenants:

Supported global config types:

TypeFileCommand Example
D&R Ruleshives/dr-general.yaml"Add detection for X"
False Positiveshives/fp.yaml"Add FP rule for Y"
Outputshives/outputs.yaml"Add Slack output"
Extensionshives/extensions.yaml"Enable Zeek extension"
FIMhives/integrity.yaml"Add FIM for /etc/passwd"
Artifact Collectionhives/artifact.yaml"Collect auth.log"
Exfil Watchhives/exfil.yaml"Watch for large uploads"
Resourceshives/resources.yaml"Add payload X"
Installation Keyshives/installation_keys.yaml"Add Windows install key"

Add Tenant-Specific Configuration

"Add custom FIM for acme-corp to watch /opt/app" "acme-corp needs a custom Slack output"

Adds configuration specific to ONE tenant:

Workflow:

  1. Look up OID from org-manifest.yaml
  2. Determine config type
  3. Create/update appropriate file in orgs/<oid>/custom/
  4. Update orgs/<oid>/index.yaml to include it
  5. Commit changes

Import All Rules from Tenant

"Import all rules from acme-corp" "Bootstrap IaC from globex's current config"

Imports ALL D&R rules from a tenant into the IaC repo:

Workflow:

  1. Look up tenant OID
  2. Fetch all rules using list_dr_general_rules and get_dr_general_rule
  3. Ask user: Add as global or tenant-specific?
  4. Add rules to appropriate location
  5. Commit: "Import N rules from [tenant]"

Repository Operations

List Tenants

"Show tenants in IaC" or "List orgs"

IaC Repository Tenants
══════════════════════

Friendly Name    OID                                    Custom Configs
─────────────────────────────────────────────────────────────────────
acme-corp        7e41e07b-c44c-43a3-b78d-41f34204789d   rules, fim
globex           a326700d-3cd7-49d1-ad08-20b396d8549d   (none)
initech          cb639126-e0bc-4563-a577-2e559c0610b2   outputs

Total: 3 tenants

Show Repository Structure

"Show IaC structure" or "What's in the repo?"

Displays the current repository layout with file summaries.


Validate Repository

"Validate IaC repo" or "Check for errors"

Validates the repository structure and configurations:

Checks:

  • All index.yaml files have valid includes
  • Include paths resolve to existing files
  • YAML syntax is valid
  • D&R rules pass validation
  • No orphaned org folders (not in manifest)
  • No missing org folders (in manifest but no folder)

Sync from LimaCharlie

"Sync acme-corp from LC" or "Pull current config for globex"

Exports current configuration from LimaCharlie into the repository:

Workflow:

  1. Look up OID from manifest
  2. Use ext-git-sync export OR limacharlie configs fetch
  3. Place exported config in exports/orgs/<oid>/
  4. Optionally: Merge into main org folder
  5. Show diff if merging

Deploy (Local)

"Deploy acme-corp" or "Push configs to LC"

Deploys configuration to LimaCharlie using the CLI:

limacharlie configs push \
  --oid <oid> \
  --config ./orgs/<oid>/index.yaml \
  --force \
  --hive-dr-general \
  --hive-fp \
  --outputs \
  --integrity \
  --artifact \
  --exfil \
  --resources \
  --extensions \
  --installation-keys

Note: For production, recommend using ext-git-sync's recurring sync.


D&R Rule Generation

CRITICAL: Never write D&R YAML manually. Always use AI generation.

When creating NEW detection rules:

1. generate_dr_rule_detection
   → Generates detection component from natural language

2. generate_dr_rule_respond
   → Generates response component from natural language

3. validate_dr_rule_components
   → Validates before adding to repo

When IMPORTING existing rules from LC, fetch them via API - no generation needed.


ext-git-sync Setup Guide

After initializing the repo and adding tenants, each org needs ext-git-sync configured:

Per-Organization Setup

  1. Subscribe to ext-git-sync extension in each org:

    subscribe_to_extension(oid, "ext-git-sync")
    
  2. Create SSH deploy key:

    ssh-keygen -t ed25519 -C "lc-gitsync-<org-name>" -f ~/.ssh/lc-gitsync
    
  3. Add public key to GitHub (Settings → Deploy keys → Allow write access)

  4. Store private key in LC Secret Manager for each org:

    set_secret(oid, "git-sync-ssh-key", <private_key_content>)
    
  5. Configure ext-git-sync using the exact config schema below

ext-git-sync Config Schema

CRITICAL: Use these exact field names when configuring ext-git-sync:

# Required fields
repo_url: "git@github.com:your-org/your-repo.git"    # NOT "repository"
branch: "main"
conf_root: "orgs/<oid>/index.yaml"                   # Path to org's config entry point

# SSH authentication (recommended)
ssh_key_source: "secret"                              # Use LC Secret Manager
ssh_key_secret_name: "git-sync-ssh-key"              # Name of secret containing private key

# Alternative: inline SSH key (not recommended for production)
# ssh_key_source: "inline"
# ssh_key: "<private_key_content>"

API Call Example:

set_extension_config(
  oid: "<org-oid>",
  extension_name: "ext-git-sync",
  config_data: {
    "repo_url": "git@github.com:your-org/your-repo.git",
    "branch": "main",
    "conf_root": "orgs/<oid>/index.yaml",
    "ssh_key_source": "secret",
    "ssh_key_secret_name": "git-sync-ssh-key"
  }
)

Shared SSH Key Option

For MSSP scenarios, you can use ONE deploy key across all orgs:

  1. Create single SSH key
  2. Add to GitHub repo
  3. Store same private key in each org's Secret Manager (same secret name)
  4. Configure ext-git-sync in each org pointing to same repo

Verify ext-git-sync Setup

After configuration, verify the setup is working:

  1. Check extension subscription:

    list_extension_configs(oid)
    → Should show ext-git-sync in the list
    
  2. Verify secret exists:

    list_secrets(oid)
    → Should include "git-sync-ssh-key"
    
  3. Check extension config:

    get_extension_config(oid, "ext-git-sync")
    → Verify repo_url, branch, conf_root are correct
    
  4. Check for org errors:

    get_org_errors(oid)
    → Look for ext-git-sync errors (SSH auth failures, repo access issues)
    
  5. Trigger manual sync (optional):

    • In LC UI: Extensions → ext-git-sync → "Sync Now"
    • Check org errors afterward for any issues

Repository Layout Reference

my-lc-iac/
├── org-manifest.yaml              # Friendly name → OID mapping
│
├── hives/                         # Global configurations
│   ├── dr-general.yaml            # Detection rules
│   ├── fp.yaml                    # False positive rules
│   ├── outputs.yaml               # Output destinations
│   ├── extensions.yaml            # Extensions to enable
│   ├── integrity.yaml             # FIM rules
│   ├── artifact.yaml              # Artifact collection
│   ├── exfil.yaml                 # Exfil monitoring
│   ├── resources.yaml             # Resources/payloads
│   └── installation_keys.yaml     # Sensor install keys
│
├── orgs/                          # Per-tenant configurations
│   ├── 7e41e07b-...-789d/         # acme-corp (OID)
│   │   ├── index.yaml             # Includes global + custom
│   │   └── custom/                # Tenant-specific
│   │       ├── rules.yaml
│   │       └── fim.yaml
│   │
│   └── a326700d-...-549d/         # globex (OID)
│       └── index.yaml
│
├── exports/                       # ext-git-sync exports land here
│   └── orgs/
│       └── ...
│
├── README.md
└── .gitignore

YAML Structure Reference

hives/dr-general.yaml

version: 3
hives:
  dr-general:
    rule-name-here:
      data:
        detect:
          event: NEW_PROCESS
          op: contains
          path: event/COMMAND_LINE
          value: "-enc"
        respond:
          - action: report
            name: encoded-powershell
      usr_mtd:
        enabled: true
        expiry: 0
        tags: []

hives/extensions.yaml

version: 3
extensions:
  - ext-infrastructure
  - ext-velociraptor
  - ext-reliable-tasking

hives/outputs.yaml

version: 3
outputs:
  slack-alerts:
    for: detect
    module: slack
    slack_api_token: hive://secret/slack-token
    slack_channel: "#security-alerts"

hives/integrity.yaml (FIM)

version: 3
integrity:
  ssh-keys:
    patterns:
      - /root/.ssh/authorized_keys
      - /home/*/.ssh/authorized_keys
    platforms:
      - linux
    tags: []

hives/installation_keys.yaml

version: 3
installation_keys:
  windows:
    desc: "Windows endpoints"
    tags:
      - windows
  linux:
    desc: "Linux servers"
    tags:
      - linux

org-manifest.yaml

version: 1
orgs:
  acme-corp:
    oid: 7e41e07b-c44c-43a3-b78d-41f34204789d
    description: "Acme Corporation - Production"
    added: "2025-11-30"

  globex:
    oid: a326700d-3cd7-49d1-ad08-20b396d8549d
    description: "Globex Industries"
    added: "2025-11-30"

Best Practices

1. Git Workflow

  • Use branches for changes
  • Review via PR before merging to main
  • Let ext-git-sync handle deployment from main branch

2. Rule Naming

Use consistent naming: [category]-[description]

  • encoded-powershell-execution
  • mimikatz-command-line
  • lateral-movement-psexec

3. Tenant Customization

  • Keep global configs as defaults
  • Only add tenant-specific configs when truly needed
  • Document why custom configs exist

4. Secrets

  • Never commit plaintext secrets
  • Use LC Secret Manager: hive://secret/secret-name
  • Reference secrets in configs, don't embed values

5. Testing Changes

  • Use limacharlie configs push --dry-run before deploying
  • Test on one org before rolling out globally
  • Use detection-engineering skill to test rules

6. Importing vs Creating

  • Import when rule already exists and works well in LC
  • Create when building new detection logic
  • Promote when a tenant-specific rule should be global

Troubleshooting

General Issues

IssueSolution
Include path not foundCheck relative path from index.yaml location
YAML syntax errorValidate with python -c "import yaml; yaml.safe_load(open('file.yaml'))"
Org not in manifestRun "add tenant" command
Rule not appearingCheck enabled: true in usr_mtd
Rule exists in LC but not IaCUse "import rule" command

ext-git-sync Specific Issues

IssueCauseSolution
"repo_url is required"Wrong field nameUse repo_url, not repository
"ssh_key is required"Secret doesn't exist or wrong nameVerify secret exists with list_secrets(oid)
"conf_root not found"Wrong path in configUse full path: orgs/<oid>/index.yaml
SSH auth failureDeploy key not added or wrong keyVerify public key is in GitHub deploy keys
"Host key verification failed"First connection to GitHubAdd GitHub to known_hosts or use ssh -o StrictHostKeyChecking=no
Sync runs but no changesBranch mismatchVerify branch field matches your repo's default branch
Extension not in listNot subscribedRun subscribe_to_extension(oid, "ext-git-sync")

Debugging ext-git-sync

  1. Check org errors first:

    get_org_errors(oid)
    

    This shows recent errors from ext-git-sync including SSH failures and config issues.

  2. Verify the complete config:

    get_extension_config(oid, "ext-git-sync")
    

    Ensure all required fields are present: repo_url, branch, conf_root, ssh_key_source, ssh_key_secret_name

  3. Test SSH key locally:

    ssh -i ~/.ssh/your-key -T git@github.com
    

    Should return: "Hi username! You've successfully authenticated..."

  4. Verify GitHub deploy key permissions:

    • Must have "Allow write access" checked if using bidirectional sync
    • Key must be added to the specific repository, not account-level

Command Quick Reference

CommandExample
Initialize repo"Set up IaC repo at ~/lc-config"
Add tenant"Add tenant acme-corp"
Create tenant"Create new org called acme-corp"
Add global rule"Add detection for encoded PowerShell"
Import rule"Import rule X from acme-corp"
Promote rule"Promote rule X from acme-corp to global"
Copy rule"Copy rule X from acme-corp to globex"
Add tenant rule"Add custom rule for acme-corp only"
List rules"Show global rules"
List tenants"Show tenants in IaC"
Validate"Validate IaC repo"
Deploy"Deploy acme-corp"
Sync"Sync acme-corp from LC"

SkillUse Case
detection-engineeringTest and refine D&R rules before adding to IaC
lookup-lc-docReference D&R syntax and operators
reportingGenerate reports across managed orgs

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon