@openape/cli 0.1.2 ā 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/install-proxy-apes.js +135 -0
- package/dist/index.js +13 -5
- package/package.json +1 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import { writeFileSync } from 'node:fs';
|
|
4
|
+
import { ask, closePrompt, isMacOS } from '../utils.js';
|
|
5
|
+
const CONFIG_DIR = '/etc/openape-proxy';
|
|
6
|
+
const CONFIG_PATH = `${CONFIG_DIR}/config.toml`;
|
|
7
|
+
const INSTALL_DIR = '/opt/openape-proxy';
|
|
8
|
+
const LAUNCHD_LABEL = 'ai.openape.proxy';
|
|
9
|
+
const LAUNCHD_PLIST = `/Library/LaunchDaemons/${LAUNCHD_LABEL}.plist`;
|
|
10
|
+
function apes(reason, cmd) {
|
|
11
|
+
// Find apes key ā prefer user's SSH key
|
|
12
|
+
const keyPaths = [
|
|
13
|
+
`${process.env.HOME}/.ssh/id_ed25519`,
|
|
14
|
+
`${process.env.HOME}/.ssh/id_ecdsa`,
|
|
15
|
+
`${process.env.HOME}/.ssh/id_rsa`,
|
|
16
|
+
];
|
|
17
|
+
const keyPath = keyPaths.find(p => existsSync(p));
|
|
18
|
+
if (!keyPath) {
|
|
19
|
+
throw new Error('No SSH key found. apes needs --key to authenticate.');
|
|
20
|
+
}
|
|
21
|
+
console.log(`\nš Requesting grant: ${reason}`);
|
|
22
|
+
execSync(`apes --key ${keyPath} --reason "${reason}" -- ${cmd}`, {
|
|
23
|
+
stdio: 'inherit',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export async function installProxyApes() {
|
|
27
|
+
// Check apes is installed
|
|
28
|
+
try {
|
|
29
|
+
execSync('which apes', { stdio: 'ignore' });
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new Error('apes is not installed. Run: sudo npx @openape/cli install-sudo');
|
|
33
|
+
}
|
|
34
|
+
console.log('\nš¾ OpenApe Proxy Installer (via apes)\n');
|
|
35
|
+
console.log('This installer uses apes for privilege elevation.');
|
|
36
|
+
console.log('Each privileged step requires approval from your admin.\n');
|
|
37
|
+
// Gather config interactively (no root needed)
|
|
38
|
+
const idpUrl = await ask('IdP URL', 'https://id.test.openape.at');
|
|
39
|
+
const agentEmail = await ask('Agent email');
|
|
40
|
+
const listen = await ask('Listen address', '127.0.0.1:9090');
|
|
41
|
+
const defaultAction = await ask('Default action (block/request/request-async)', 'block');
|
|
42
|
+
const auditLog = await ask('Audit log path', '/var/log/openape-proxy/audit.log');
|
|
43
|
+
closePrompt();
|
|
44
|
+
// Generate config locally in /tmp
|
|
45
|
+
const config = `# OpenApe Proxy Configuration
|
|
46
|
+
# Generated by: openape install-proxy --via-apes
|
|
47
|
+
|
|
48
|
+
[proxy]
|
|
49
|
+
listen = "${listen}"
|
|
50
|
+
idp_url = "${idpUrl}"
|
|
51
|
+
agent_email = "${agentEmail}"
|
|
52
|
+
default_action = "${defaultAction}"
|
|
53
|
+
audit_log = "${auditLog}"
|
|
54
|
+
|
|
55
|
+
# Add your rules below:
|
|
56
|
+
|
|
57
|
+
# [[allow]]
|
|
58
|
+
# domain = "api.github.com"
|
|
59
|
+
# methods = ["GET"]
|
|
60
|
+
# note = "GitHub read-only"
|
|
61
|
+
|
|
62
|
+
# [[deny]]
|
|
63
|
+
# domain = "*.malware.example.com"
|
|
64
|
+
# note = "Blocked"
|
|
65
|
+
|
|
66
|
+
# [[grant_required]]
|
|
67
|
+
# domain = "api.github.com"
|
|
68
|
+
# methods = ["POST", "PUT", "DELETE"]
|
|
69
|
+
# grant_type = "allow_once"
|
|
70
|
+
# note = "Needs approval"
|
|
71
|
+
`;
|
|
72
|
+
const tmpConfig = '/tmp/openape-proxy-config.toml';
|
|
73
|
+
writeFileSync(tmpConfig, config);
|
|
74
|
+
console.log(`\nš Config prepared at ${tmpConfig}`);
|
|
75
|
+
// Step 1: Create config directory
|
|
76
|
+
apes('Create OpenApe Proxy config directory', `mkdir -p ${CONFIG_DIR}`);
|
|
77
|
+
apes('Set permissions on config directory', `chmod 700 ${CONFIG_DIR}`);
|
|
78
|
+
// Step 2: Copy config
|
|
79
|
+
apes('Install proxy config', `cp ${tmpConfig} ${CONFIG_PATH}`);
|
|
80
|
+
apes('Secure proxy config (root-only)', `chmod 600 ${CONFIG_PATH}`);
|
|
81
|
+
// Step 3: Create audit log directory
|
|
82
|
+
const auditDir = auditLog.substring(0, auditLog.lastIndexOf('/'));
|
|
83
|
+
if (auditDir) {
|
|
84
|
+
apes('Create audit log directory', `mkdir -p ${auditDir}`);
|
|
85
|
+
}
|
|
86
|
+
// Step 4: Clone/update proxy source
|
|
87
|
+
if (existsSync(`${INSTALL_DIR}/package.json`)) {
|
|
88
|
+
apes('Update proxy source', `git -C ${INSTALL_DIR} pull`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
apes('Download proxy source', `git clone https://github.com/openape-ai/proxy.git ${INSTALL_DIR}`);
|
|
92
|
+
}
|
|
93
|
+
// Step 5: Install dependencies
|
|
94
|
+
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
95
|
+
apes('Install proxy dependencies', `${bunPath} install --cwd ${INSTALL_DIR}`);
|
|
96
|
+
// Step 6: Set up system service
|
|
97
|
+
if (isMacOS()) {
|
|
98
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
99
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
100
|
+
<plist version="1.0">
|
|
101
|
+
<dict>
|
|
102
|
+
<key>Label</key>
|
|
103
|
+
<string>${LAUNCHD_LABEL}</string>
|
|
104
|
+
<key>ProgramArguments</key>
|
|
105
|
+
<array>
|
|
106
|
+
<string>${bunPath}</string>
|
|
107
|
+
<string>run</string>
|
|
108
|
+
<string>${INSTALL_DIR}/src/index.ts</string>
|
|
109
|
+
<string>--config</string>
|
|
110
|
+
<string>${CONFIG_PATH}</string>
|
|
111
|
+
</array>
|
|
112
|
+
<key>RunAtLoad</key>
|
|
113
|
+
<true/>
|
|
114
|
+
<key>KeepAlive</key>
|
|
115
|
+
<true/>
|
|
116
|
+
<key>StandardOutPath</key>
|
|
117
|
+
<string>/var/log/openape-proxy/stdout.log</string>
|
|
118
|
+
<key>StandardErrorPath</key>
|
|
119
|
+
<string>/var/log/openape-proxy/stderr.log</string>
|
|
120
|
+
<key>WorkingDirectory</key>
|
|
121
|
+
<string>${INSTALL_DIR}</string>
|
|
122
|
+
</dict>
|
|
123
|
+
</plist>`;
|
|
124
|
+
const tmpPlist = '/tmp/openape-proxy-launchd.plist';
|
|
125
|
+
writeFileSync(tmpPlist, plist);
|
|
126
|
+
apes('Install launchd service', `cp ${tmpPlist} ${LAUNCHD_PLIST}`);
|
|
127
|
+
apes('Load proxy service', `launchctl load ${LAUNCHD_PLIST}`);
|
|
128
|
+
}
|
|
129
|
+
console.log('\nš OpenApe Proxy installed via apes!\n');
|
|
130
|
+
console.log(` Config: ${CONFIG_PATH}`);
|
|
131
|
+
console.log(` Proxy: ${INSTALL_DIR}`);
|
|
132
|
+
console.log(` Audit log: ${auditLog}`);
|
|
133
|
+
console.log(` Listening: ${listen}`);
|
|
134
|
+
console.log('\n Every step was approved by your admin. š\n');
|
|
135
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { installProxy } from './commands/install-proxy.js';
|
|
3
|
+
import { installProxyApes } from './commands/install-proxy-apes.js';
|
|
3
4
|
import { installSudo } from './commands/install-sudo.js';
|
|
4
5
|
const command = process.argv[2];
|
|
5
6
|
const HELP = `
|
|
@@ -8,18 +9,25 @@ OpenApe CLI ā install and manage OpenApe components
|
|
|
8
9
|
Usage: openape <command> [options]
|
|
9
10
|
|
|
10
11
|
Commands:
|
|
11
|
-
install-proxy
|
|
12
|
-
install-
|
|
13
|
-
|
|
12
|
+
install-proxy Install the OpenApe HTTP proxy (requires sudo)
|
|
13
|
+
install-proxy --via-apes Install the proxy using apes for elevation (no sudo needed!)
|
|
14
|
+
install-sudo Install apes privilege elevation (requires sudo)
|
|
15
|
+
help Show this help message
|
|
14
16
|
|
|
15
17
|
Examples:
|
|
16
|
-
sudo openape install-proxy
|
|
18
|
+
sudo openape install-proxy # traditional sudo
|
|
19
|
+
openape install-proxy --via-apes # agent-friendly, each step approved
|
|
17
20
|
sudo openape install-sudo
|
|
18
21
|
`;
|
|
19
22
|
async function main() {
|
|
20
23
|
switch (command) {
|
|
21
24
|
case 'install-proxy':
|
|
22
|
-
|
|
25
|
+
if (process.argv.includes('--via-apes')) {
|
|
26
|
+
await installProxyApes();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
await installProxy();
|
|
30
|
+
}
|
|
23
31
|
break;
|
|
24
32
|
case 'install-sudo':
|
|
25
33
|
await installSudo();
|