feat(coder-labs/modules/codex): add boundary support via agentapi module (#795)
## Description Adds boundary support to the Codex module by passing boundary variables through to the agentapi module and using AGENTAPI_BOUNDARY_PREFIX in the start script. Depends on #780 ## Type of Change - [x] Feature/enhancement ## Module Information **Path:** `registry/coder-labs/modules/codex` **Breaking change:** No --------- Co-authored-by: Shane White <shane.white@cloudsecure.ltd> Co-authored-by: 35C4n0r <70096901+35C4n0r@users.noreply.github.com>
This commit is contained in:
parent
2ee14fdf6e
commit
a0430e6f83
@ -13,7 +13,7 @@ Run Codex CLI in your workspace to access OpenAI's models through the Codex inte
|
|||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = var.openai_api_key
|
openai_api_key = var.openai_api_key
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
@ -32,7 +32,7 @@ module "codex" {
|
|||||||
module "codex" {
|
module "codex" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
@ -51,7 +51,7 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage
|
|||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
enable_aibridge = true
|
enable_aibridge = true
|
||||||
@ -94,7 +94,7 @@ data "coder_task" "me" {}
|
|||||||
|
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
ai_prompt = data.coder_task.me.prompt
|
ai_prompt = data.coder_task.me.prompt
|
||||||
@ -105,6 +105,26 @@ module "codex" {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Usage with Agent Boundaries
|
||||||
|
|
||||||
|
This example shows how to configure the Codex module to run the agent behind a process-level boundary that restricts its network access.
|
||||||
|
|
||||||
|
By default, when `enable_boundary = true`, the module uses `coder boundary` subcommand (provided by Coder) without requiring any installation.
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "codex" {
|
||||||
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
|
version = "4.3.0"
|
||||||
|
agent_id = coder_agent.main.id
|
||||||
|
openai_api_key = var.openai_api_key
|
||||||
|
workdir = "/home/coder/project"
|
||||||
|
enable_boundary = true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> For developers: The module also supports installing boundary from a release version (`use_boundary_directly = true`) or compiling from source (`compile_boundary_from_source = true`). These are escape hatches for development and testing purposes.
|
||||||
|
|
||||||
### Advanced Configuration
|
### Advanced Configuration
|
||||||
|
|
||||||
This example shows additional configuration options for custom models, MCP servers, and base configuration.
|
This example shows additional configuration options for custom models, MCP servers, and base configuration.
|
||||||
@ -112,7 +132,7 @@ This example shows additional configuration options for custom models, MCP serve
|
|||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
|
|||||||
@ -473,4 +473,47 @@ describe("codex", async () => {
|
|||||||
);
|
);
|
||||||
expect(configToml).toContain('profile = "aibridge"');
|
expect(configToml).toContain('profile = "aibridge"');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("boundary-enabled", async () => {
|
||||||
|
const { id } = await setup({
|
||||||
|
moduleVariables: {
|
||||||
|
enable_boundary: "true",
|
||||||
|
boundary_config_path: "/tmp/test-boundary.yaml",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Write boundary config
|
||||||
|
await execContainer(id, [
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
`cat > /tmp/test-boundary.yaml <<'EOF'
|
||||||
|
jail_type: landjail
|
||||||
|
proxy_port: 8087
|
||||||
|
log_level: warn
|
||||||
|
allowlist:
|
||||||
|
- "domain=api.openai.com"
|
||||||
|
EOF`,
|
||||||
|
]);
|
||||||
|
// Add mock coder binary for boundary setup
|
||||||
|
await writeExecutable({
|
||||||
|
containerId: id,
|
||||||
|
filePath: "/usr/bin/coder",
|
||||||
|
content: `#!/bin/bash
|
||||||
|
if [ "$1" = "boundary" ]; then
|
||||||
|
if [ "$2" = "--help" ]; then
|
||||||
|
echo "boundary help"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
shift; shift; exec "$@"
|
||||||
|
fi
|
||||||
|
echo "mock coder"`,
|
||||||
|
});
|
||||||
|
await execModuleScript(id);
|
||||||
|
await expectAgentAPIStarted(id);
|
||||||
|
// Verify boundary wrapper was used in start script
|
||||||
|
const startLog = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.codex-module/agentapi-start.log",
|
||||||
|
);
|
||||||
|
expect(startLog).toContain("boundary");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -176,6 +176,36 @@ variable "codex_system_prompt" {
|
|||||||
default = "You are a helpful coding assistant. Start every response with `Codex says:`"
|
default = "You are a helpful coding assistant. Start every response with `Codex says:`"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "enable_boundary" {
|
||||||
|
type = bool
|
||||||
|
description = "Enable coder boundary for network filtering."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "boundary_config_path" {
|
||||||
|
type = string
|
||||||
|
description = "Path to boundary config.yaml inside the workspace. If provided, exposed as BOUNDARY_CONFIG env var."
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "boundary_version" {
|
||||||
|
type = string
|
||||||
|
description = "Boundary version. When use_boundary_directly is true, a release version should be provided or 'latest' for the latest release."
|
||||||
|
default = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "compile_boundary_from_source" {
|
||||||
|
type = bool
|
||||||
|
description = "Whether to compile boundary from source instead of using the official install script."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "use_boundary_directly" {
|
||||||
|
type = bool
|
||||||
|
description = "Whether to use boundary binary directly instead of coder boundary subcommand."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
resource "coder_env" "openai_api_key" {
|
resource "coder_env" "openai_api_key" {
|
||||||
agent_id = var.agent_id
|
agent_id = var.agent_id
|
||||||
name = "OPENAI_API_KEY"
|
name = "OPENAI_API_KEY"
|
||||||
@ -212,7 +242,7 @@ locals {
|
|||||||
|
|
||||||
module "agentapi" {
|
module "agentapi" {
|
||||||
source = "registry.coder.com/coder/agentapi/coder"
|
source = "registry.coder.com/coder/agentapi/coder"
|
||||||
version = "2.2.0"
|
version = "2.3.0"
|
||||||
|
|
||||||
agent_id = var.agent_id
|
agent_id = var.agent_id
|
||||||
folder = local.workdir
|
folder = local.workdir
|
||||||
@ -231,6 +261,11 @@ module "agentapi" {
|
|||||||
enable_state_persistence = var.enable_state_persistence
|
enable_state_persistence = var.enable_state_persistence
|
||||||
pre_install_script = var.pre_install_script
|
pre_install_script = var.pre_install_script
|
||||||
post_install_script = var.post_install_script
|
post_install_script = var.post_install_script
|
||||||
|
enable_boundary = var.enable_boundary
|
||||||
|
boundary_config_path = var.boundary_config_path
|
||||||
|
boundary_version = var.boundary_version
|
||||||
|
compile_boundary_from_source = var.compile_boundary_from_source
|
||||||
|
use_boundary_directly = var.use_boundary_directly
|
||||||
start_script = <<-EOT
|
start_script = <<-EOT
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -o errexit
|
set -o errexit
|
||||||
|
|||||||
@ -210,7 +210,16 @@ capture_session_id() {
|
|||||||
|
|
||||||
start_codex() {
|
start_codex() {
|
||||||
printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}"
|
printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}"
|
||||||
|
# AGENTAPI_BOUNDARY_PREFIX is set by the agentapi module's main.sh when
|
||||||
|
# enable_boundary=true. It points to a wrapper script that runs the command
|
||||||
|
# through coder boundary, sandboxing only the agent process.
|
||||||
|
if [ -n "${AGENTAPI_BOUNDARY_PREFIX:-}" ]; then
|
||||||
|
printf "Starting with coder boundary enabled\n"
|
||||||
|
agentapi server --type codex --term-width 67 --term-height 1190 -- \
|
||||||
|
"${AGENTAPI_BOUNDARY_PREFIX}" codex "${CODEX_ARGS[@]}" &
|
||||||
|
else
|
||||||
agentapi server --type codex --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" &
|
agentapi server --type codex --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" &
|
||||||
|
fi
|
||||||
capture_session_id
|
capture_session_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user