golv 1.1.0__py3-none-any.whl
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.
- golv/__init__.py +25 -0
- golv/agent.py +142 -0
- golv/client.py +158 -0
- golv/exeptions.py +19 -0
- golv/models.py +111 -0
- golv/setup_golv.py +100 -0
- golv-1.1.0.dist-info/METADATA +197 -0
- golv-1.1.0.dist-info/RECORD +12 -0
- golv-1.1.0.dist-info/WHEEL +5 -0
- golv-1.1.0.dist-info/entry_points.txt +2 -0
- golv-1.1.0.dist-info/licenses/LICENSE +21 -0
- golv-1.1.0.dist-info/top_level.txt +1 -0
golv/__init__.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .setup_golv import GoLVSetup
|
|
2
|
+
from .client import GoLVClient
|
|
3
|
+
from .agent import GoLVAgent
|
|
4
|
+
from .models import (
|
|
5
|
+
VMConfig, VMType, CommandResult,
|
|
6
|
+
CommandRequest, CommandSecurityLevel, VMStatus, AgentConfig
|
|
7
|
+
)
|
|
8
|
+
from .exceptions import GoLVError, AuthError, VMNotFoundError, SecurityError
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"GoLVSetup",
|
|
12
|
+
"GoLVClient",
|
|
13
|
+
"GoLVAgent",
|
|
14
|
+
"VMConfig",
|
|
15
|
+
"VMType",
|
|
16
|
+
"CommandResult",
|
|
17
|
+
"CommandRequest",
|
|
18
|
+
"CommandSecurityLevel",
|
|
19
|
+
"VMStatus",
|
|
20
|
+
"AgentConfig",
|
|
21
|
+
"GoLVError",
|
|
22
|
+
"AuthError",
|
|
23
|
+
"VMNotFoundError",
|
|
24
|
+
"SecurityError",
|
|
25
|
+
]
|
golv/agent.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from typing import Optional, List, Dict, Any
|
|
2
|
+
from .client import GoLVClient
|
|
3
|
+
from .models import VMConfig, AgentConfig, CommandSecurityLevel, CommandResult
|
|
4
|
+
from .exceptions import SecurityError
|
|
5
|
+
|
|
6
|
+
class GoLVAgent:
|
|
7
|
+
"""Agent sécurisé pour l'exécution de commandes par IA"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, config: AgentConfig):
|
|
10
|
+
self.config = config
|
|
11
|
+
self.client = GoLVClient(api_key=config.api_key)
|
|
12
|
+
|
|
13
|
+
# Initialiser ou créer la VM
|
|
14
|
+
if config.vm_config.vm_id:
|
|
15
|
+
self.vm_id = config.vm_config.vm_id
|
|
16
|
+
else:
|
|
17
|
+
self._create_vm()
|
|
18
|
+
|
|
19
|
+
def _create_vm(self):
|
|
20
|
+
"""Créer une nouvelle VM selon la configuration"""
|
|
21
|
+
vm_data = self.client.create_vm(self.config.vm_config)
|
|
22
|
+
self.vm_id = vm_data.get("vm_id")
|
|
23
|
+
print(f"✅ VM créée: {self.vm_id}")
|
|
24
|
+
|
|
25
|
+
def _validate_command(self, command: str) -> bool:
|
|
26
|
+
"""Valider une commande pour la sécurité"""
|
|
27
|
+
# Longueur maximale
|
|
28
|
+
if len(command) > self.config.max_command_length:
|
|
29
|
+
raise SecurityError(f"Commande trop longue ({len(command)} > {self.config.max_command_length})")
|
|
30
|
+
|
|
31
|
+
# Commandes bannies
|
|
32
|
+
banned_patterns = [
|
|
33
|
+
"rm -rf", "shutdown", "reboot", "dd", "mkfs",
|
|
34
|
+
":(){", "chmod 777", "> /dev/sda", "mkfifo"
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
for banned in banned_patterns:
|
|
38
|
+
if banned in command.lower():
|
|
39
|
+
raise SecurityError(f"Commande bannie détectée: {banned}")
|
|
40
|
+
|
|
41
|
+
# Vérifier si la commande est autorisée
|
|
42
|
+
if self.config.use_command:
|
|
43
|
+
first_word = command.split()[0] if command.split() else ""
|
|
44
|
+
|
|
45
|
+
# Toujours autoriser echo et python
|
|
46
|
+
if first_word in ["echo", "python", "python3"]:
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
# Vérifier dans la liste des commandes autorisées
|
|
50
|
+
if first_word not in self.config.allowed_commands:
|
|
51
|
+
raise SecurityError(f"Commande non autorisée: {first_word}")
|
|
52
|
+
|
|
53
|
+
return True
|
|
54
|
+
|
|
55
|
+
def execute(self, command: str, timeout: Optional[int] = None) -> CommandResult:
|
|
56
|
+
"""Exécuter une commande de manière sécurisée"""
|
|
57
|
+
try:
|
|
58
|
+
# Validation de sécurité
|
|
59
|
+
self._validate_command(command)
|
|
60
|
+
|
|
61
|
+
# Exécution
|
|
62
|
+
result = self.client.execute_command(
|
|
63
|
+
vm_id=self.vm_id,
|
|
64
|
+
command=command,
|
|
65
|
+
timeout=timeout or self.config.timeout
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Journalisation
|
|
69
|
+
self._log_execution(command, result)
|
|
70
|
+
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
return CommandResult(
|
|
75
|
+
success=False,
|
|
76
|
+
stdout="",
|
|
77
|
+
stderr=f"Erreur sécurité: {str(e)}",
|
|
78
|
+
return_code=1,
|
|
79
|
+
vm_id=self.vm_id,
|
|
80
|
+
command=command,
|
|
81
|
+
duration_ms=0,
|
|
82
|
+
executed_at=""
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def execute_safe(self, command: str) -> str:
|
|
86
|
+
"""Exécuter une commande et retourner seulement la sortie"""
|
|
87
|
+
result = self.execute(command)
|
|
88
|
+
return result.stdout if result.success else f"Erreur: {result.stderr}"
|
|
89
|
+
|
|
90
|
+
def execute_python(self, code: str) -> CommandResult:
|
|
91
|
+
"""Exécuter du code Python"""
|
|
92
|
+
# Échapper les guillemets
|
|
93
|
+
escaped_code = code.replace('"', '\\"').replace("'", "\\'")
|
|
94
|
+
command = f'python3 -c "{escaped_code}"'
|
|
95
|
+
return self.execute(command)
|
|
96
|
+
|
|
97
|
+
def execute_git(self, git_command: str) -> CommandResult:
|
|
98
|
+
"""Exécuter une commande Git"""
|
|
99
|
+
if "git" not in self.config.allowed_commands:
|
|
100
|
+
raise SecurityError("Commandes Git non autorisées")
|
|
101
|
+
|
|
102
|
+
command = f"git {git_command}"
|
|
103
|
+
return self.execute(command)
|
|
104
|
+
|
|
105
|
+
def predefined(self, command_type: str) -> CommandResult:
|
|
106
|
+
"""Exécuter une commande pré-définie"""
|
|
107
|
+
return self.client.execute_predefined(self.vm_id, command_type)
|
|
108
|
+
|
|
109
|
+
def get_status(self) -> Dict[str, Any]:
|
|
110
|
+
"""Récupérer le statut de la VM"""
|
|
111
|
+
return self.client.get_vm_status(self.vm_id)
|
|
112
|
+
|
|
113
|
+
def _log_execution(self, command: str, result: CommandResult):
|
|
114
|
+
"""Journaliser l'exécution (peut être étendu)"""
|
|
115
|
+
status = "✅" if result.success else "❌"
|
|
116
|
+
print(f"{status} [{result.duration_ms}ms] {command[:50]}...")
|
|
117
|
+
|
|
118
|
+
def interactive_session(self):
|
|
119
|
+
"""Session interactive pour débogage"""
|
|
120
|
+
print(f"🔧 Session interactive GoLV Agent")
|
|
121
|
+
print(f"VM ID: {self.vm_id}")
|
|
122
|
+
print(f"Sécurité: {self.config.security_level.value}")
|
|
123
|
+
print(f"Commandes autorisées: {len(self.config.allowed_commands)}")
|
|
124
|
+
print("Tapez 'exit' pour quitter")
|
|
125
|
+
print("-" * 50)
|
|
126
|
+
|
|
127
|
+
while True:
|
|
128
|
+
try:
|
|
129
|
+
cmd = input(f"golv:{self.vm_id[:8]} $ ")
|
|
130
|
+
if cmd.lower() in ['exit', 'quit', 'q']:
|
|
131
|
+
break
|
|
132
|
+
if not cmd.strip():
|
|
133
|
+
continue
|
|
134
|
+
|
|
135
|
+
result = self.execute(cmd)
|
|
136
|
+
print(result.output)
|
|
137
|
+
|
|
138
|
+
except KeyboardInterrupt:
|
|
139
|
+
print("\nInterrompu")
|
|
140
|
+
break
|
|
141
|
+
except Exception as e:
|
|
142
|
+
print(f"Erreur: {e}")
|
golv/client.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
from typing import Optional, Dict, Any, List
|
|
4
|
+
from .models import VMConfig, CommandResult
|
|
5
|
+
from .exceptions import GoLVError, AuthError, VMNotFoundError
|
|
6
|
+
|
|
7
|
+
class GoLVClient:
|
|
8
|
+
"""Client pour l'API GoLV"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, base_url: str = "https://golv.onrender.com", api_key: Optional[str] = None):
|
|
11
|
+
self.base_url = base_url.rstrip('/')
|
|
12
|
+
self.api_key = api_key
|
|
13
|
+
self.session = requests.Session()
|
|
14
|
+
|
|
15
|
+
if api_key:
|
|
16
|
+
self.session.headers.update({
|
|
17
|
+
"Authorization": f"Bearer {api_key}",
|
|
18
|
+
"Content-Type": "application/json"
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
def authenticate(self, username: str, password: str) -> str:
|
|
22
|
+
"""Authentification et récupération du token"""
|
|
23
|
+
try:
|
|
24
|
+
response = self.session.post(
|
|
25
|
+
f"{self.base_url}/api/auth/login",
|
|
26
|
+
json={"username": username, "password": password}
|
|
27
|
+
)
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
data = response.json()
|
|
30
|
+
self.api_key = data["access_token"]
|
|
31
|
+
self.session.headers.update({"Authorization": f"Bearer {self.api_key}"})
|
|
32
|
+
return self.api_key
|
|
33
|
+
except requests.exceptions.RequestException as e:
|
|
34
|
+
raise AuthError(f"Erreur d'authentification: {e}")
|
|
35
|
+
|
|
36
|
+
def create_vm(self, config: VMConfig) -> Dict[str, Any]:
|
|
37
|
+
"""Créer une nouvelle VM"""
|
|
38
|
+
try:
|
|
39
|
+
payload = {
|
|
40
|
+
"name": config.name or f"VM-{config.vm_type}",
|
|
41
|
+
"vm_type": config.vm_type.value,
|
|
42
|
+
"version": config.version,
|
|
43
|
+
"is_public": config.is_public,
|
|
44
|
+
"tags": config.tags
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
response = self.session.post(
|
|
48
|
+
f"{self.base_url}/api/vms",
|
|
49
|
+
json=payload
|
|
50
|
+
)
|
|
51
|
+
response.raise_for_status()
|
|
52
|
+
return response.json()
|
|
53
|
+
except requests.exceptions.RequestException as e:
|
|
54
|
+
raise GoLVError(f"Erreur création VM: {e}")
|
|
55
|
+
|
|
56
|
+
def execute_command(self, vm_id: str, command: str,
|
|
57
|
+
timeout: int = 30, working_dir: Optional[str] = None) -> CommandResult:
|
|
58
|
+
"""Exécuter une commande dans une VM"""
|
|
59
|
+
try:
|
|
60
|
+
payload = {
|
|
61
|
+
"command": command,
|
|
62
|
+
"timeout": timeout
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if working_dir:
|
|
66
|
+
payload["working_dir"] = working_dir
|
|
67
|
+
|
|
68
|
+
response = self.session.post(
|
|
69
|
+
f"{self.base_url}/api/vms/{vm_id}/execute",
|
|
70
|
+
json=payload
|
|
71
|
+
)
|
|
72
|
+
response.raise_for_status()
|
|
73
|
+
data = response.json()
|
|
74
|
+
|
|
75
|
+
if data.get("success"):
|
|
76
|
+
cmd_data = data["data"]
|
|
77
|
+
return CommandResult(
|
|
78
|
+
success=cmd_data["success"],
|
|
79
|
+
stdout=cmd_data["stdout"],
|
|
80
|
+
stderr=cmd_data["stderr"],
|
|
81
|
+
return_code=cmd_data.get("return_code", 0),
|
|
82
|
+
vm_id=vm_id,
|
|
83
|
+
command=command,
|
|
84
|
+
duration_ms=cmd_data["duration_ms"],
|
|
85
|
+
executed_at=cmd_data["executed_at"]
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
raise GoLVError(f"Échec exécution: {data}")
|
|
89
|
+
|
|
90
|
+
except requests.exceptions.RequestException as e:
|
|
91
|
+
if e.response and e.response.status_code == 404:
|
|
92
|
+
raise VMNotFoundError(f"VM {vm_id} non trouvée")
|
|
93
|
+
raise GoLVError(f"Erreur exécution commande: {e}")
|
|
94
|
+
|
|
95
|
+
def execute_predefined(self, vm_id: str, command_type: str) -> CommandResult:
|
|
96
|
+
"""Exécuter une commande pré-définie"""
|
|
97
|
+
try:
|
|
98
|
+
response = self.session.post(
|
|
99
|
+
f"{self.base_url}/api/vms/{vm_id}/execute/predefined",
|
|
100
|
+
json=command_type
|
|
101
|
+
)
|
|
102
|
+
response.raise_for_status()
|
|
103
|
+
data = response.json()
|
|
104
|
+
|
|
105
|
+
if data.get("success"):
|
|
106
|
+
cmd_data = data["data"]
|
|
107
|
+
return CommandResult(
|
|
108
|
+
success=cmd_data["success"],
|
|
109
|
+
stdout=cmd_data["stdout"],
|
|
110
|
+
stderr=cmd_data["stderr"],
|
|
111
|
+
return_code=cmd_data.get("return_code", 0),
|
|
112
|
+
vm_id=vm_id,
|
|
113
|
+
command=f"Predefined: {command_type}",
|
|
114
|
+
duration_ms=cmd_data["duration_ms"],
|
|
115
|
+
executed_at=cmd_data["executed_at"]
|
|
116
|
+
)
|
|
117
|
+
else:
|
|
118
|
+
raise GoLVError(f"Échec commande pré-définie: {data}")
|
|
119
|
+
|
|
120
|
+
except requests.exceptions.RequestException as e:
|
|
121
|
+
raise GoLVError(f"Erreur commande pré-définie: {e}")
|
|
122
|
+
|
|
123
|
+
def get_vm_status(self, vm_id: str) -> Dict[str, Any]:
|
|
124
|
+
"""Récupérer le statut d'une VM"""
|
|
125
|
+
try:
|
|
126
|
+
response = self.session.get(
|
|
127
|
+
f"{self.base_url}/api/vms/{vm_id}/status"
|
|
128
|
+
)
|
|
129
|
+
response.raise_for_status()
|
|
130
|
+
return response.json()
|
|
131
|
+
except requests.exceptions.RequestException as e:
|
|
132
|
+
raise GoLVError(f"Erreur statut VM: {e}")
|
|
133
|
+
|
|
134
|
+
def list_vms(self, public_only: bool = False) -> List[Dict[str, Any]]:
|
|
135
|
+
"""Lister les VMs"""
|
|
136
|
+
try:
|
|
137
|
+
response = self.session.get(
|
|
138
|
+
f"{self.base_url}/api/vms",
|
|
139
|
+
params={"public_only": public_only}
|
|
140
|
+
)
|
|
141
|
+
response.raise_for_status()
|
|
142
|
+
data = response.json()
|
|
143
|
+
return data.get("data", [])
|
|
144
|
+
except requests.exceptions.RequestException as e:
|
|
145
|
+
raise GoLVError(f"Erreur liste VMs: {e}")
|
|
146
|
+
|
|
147
|
+
def generate_api_key(self, name: str, expires_in: int = 30) -> str:
|
|
148
|
+
"""Générer une nouvelle clé API"""
|
|
149
|
+
try:
|
|
150
|
+
response = self.session.post(
|
|
151
|
+
f"{self.base_url}/api/api-key/generate",
|
|
152
|
+
json={"name": name, "expires_in": expires_in}
|
|
153
|
+
)
|
|
154
|
+
response.raise_for_status()
|
|
155
|
+
data = response.json()
|
|
156
|
+
return data.get("api_key", "")
|
|
157
|
+
except requests.exceptions.RequestException as e:
|
|
158
|
+
raise GoLVError(f"Erreur génération clé API: {e}")
|
golv/exeptions.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class GoLVError(Exception):
|
|
2
|
+
"""Exception de base pour GoLV"""
|
|
3
|
+
pass
|
|
4
|
+
|
|
5
|
+
class AuthError(GoLVError):
|
|
6
|
+
"""Erreur d'authentification"""
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
class VMNotFoundError(GoLVError):
|
|
10
|
+
"""VM non trouvée"""
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
class SecurityError(GoLVError):
|
|
14
|
+
"""Erreur de sécurité"""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
class CommandTimeoutError(GoLVError):
|
|
18
|
+
"""Timeout de commande"""
|
|
19
|
+
pass
|
golv/models.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Optional, List, Dict, Any
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
class CommandSecurityLevel(str, Enum):
|
|
6
|
+
"""Niveaux de sécurité pour les commandes"""
|
|
7
|
+
LOW = "low" # Commandes basiques (echo, ls, cat)
|
|
8
|
+
MEDIUM = "medium" # Développement (python, git, npm)
|
|
9
|
+
HIGH = "high" # Administration limitée
|
|
10
|
+
AI = "ai" # Mode spécial pour IA (toutes commandes sécurisées)
|
|
11
|
+
|
|
12
|
+
class VMType(str, Enum):
|
|
13
|
+
"""Types de VMs disponibles"""
|
|
14
|
+
UBUNTU = "ubuntu"
|
|
15
|
+
DEBIAN = "debian"
|
|
16
|
+
PYTHON_DEV = "python-dev"
|
|
17
|
+
NODEJS = "nodejs"
|
|
18
|
+
DOCKER_HOST = "docker-host"
|
|
19
|
+
WORDPRESS = "wordpress"
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class VMConfig:
|
|
23
|
+
"""Configuration d'une VM"""
|
|
24
|
+
vm_id: Optional[str] = None
|
|
25
|
+
vm_type: VMType = VMType.UBUNTU
|
|
26
|
+
version: str = "22.04 LTS"
|
|
27
|
+
name: Optional[str] = None
|
|
28
|
+
is_public: bool = False
|
|
29
|
+
tags: List[str] = field(default_factory=list)
|
|
30
|
+
|
|
31
|
+
def __post_init__(self):
|
|
32
|
+
if not self.name and self.vm_id:
|
|
33
|
+
self.name = f"VM-{self.vm_id[:8]}"
|
|
34
|
+
@dataclass
|
|
35
|
+
class CommandRequest:
|
|
36
|
+
"""Représente une commande à envoyer"""
|
|
37
|
+
command: str
|
|
38
|
+
vm_id: Optional[str] = None
|
|
39
|
+
timeout: int = 30
|
|
40
|
+
working_dir: Optional[str] = None
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class VMStatus:
|
|
44
|
+
"""Statut de la VM"""
|
|
45
|
+
vm_id: str
|
|
46
|
+
status: str
|
|
47
|
+
uptime: Optional[str] = None
|
|
48
|
+
ip_address: Optional[str] = None
|
|
49
|
+
@dataclass
|
|
50
|
+
class CommandResult:
|
|
51
|
+
"""Résultat d'exécution de commande"""
|
|
52
|
+
success: bool
|
|
53
|
+
stdout: str
|
|
54
|
+
stderr: str
|
|
55
|
+
return_code: int
|
|
56
|
+
vm_id: str
|
|
57
|
+
command: str
|
|
58
|
+
duration_ms: int
|
|
59
|
+
executed_at: str
|
|
60
|
+
|
|
61
|
+
def __str__(self):
|
|
62
|
+
status = "✅ SUCCESS" if self.success else "❌ FAILED"
|
|
63
|
+
return f"{status} [{self.duration_ms}ms] {self.command}\n{self.stdout}"
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def output(self):
|
|
67
|
+
"""Retourne la sortie principale"""
|
|
68
|
+
return self.stdout if self.success else self.stderr
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class AgentConfig:
|
|
72
|
+
"""Configuration de l'agent IA"""
|
|
73
|
+
api_key: str
|
|
74
|
+
vm_config: VMConfig
|
|
75
|
+
timeout: int = 100
|
|
76
|
+
use_command: bool = True
|
|
77
|
+
security_level: CommandSecurityLevel = CommandSecurityLevel.AI
|
|
78
|
+
allowed_commands: List[str] = field(default_factory=list)
|
|
79
|
+
max_command_length: int = 500
|
|
80
|
+
|
|
81
|
+
def __post_init__(self):
|
|
82
|
+
# Commandes autorisées par niveau de sécurité
|
|
83
|
+
self.allowed_commands = self._get_allowed_commands()
|
|
84
|
+
|
|
85
|
+
def _get_allowed_commands(self) -> List[str]:
|
|
86
|
+
"""Retourne les commandes autorisées selon le niveau"""
|
|
87
|
+
base_commands = ["pwd", "ls", "echo", "cat"]
|
|
88
|
+
|
|
89
|
+
if self.security_level == CommandSecurityLevel.LOW:
|
|
90
|
+
return base_commands
|
|
91
|
+
|
|
92
|
+
dev_commands = base_commands + [
|
|
93
|
+
"python3", "python", "pip", "node", "npm", "git",
|
|
94
|
+
"mkdir", "touch", "find", "grep"
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
if self.security_level == CommandSecurityLevel.MEDIUM:
|
|
98
|
+
return dev_commands
|
|
99
|
+
|
|
100
|
+
admin_commands = dev_commands + [
|
|
101
|
+
"curl", "wget", "df", "du", "date",
|
|
102
|
+
"whoami", "uname", "hostname"
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
if self.security_level == CommandSecurityLevel.HIGH:
|
|
106
|
+
return admin_commands
|
|
107
|
+
|
|
108
|
+
# Mode AI - toutes les commandes sécurisées
|
|
109
|
+
return admin_commands + [
|
|
110
|
+
"cd", "head", "tail", "wc", "sort", "uniq"
|
|
111
|
+
]
|
golv/setup_golv.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from .client import GoLVClient
|
|
3
|
+
from .models import VMConfig, VMType, AgentConfig
|
|
4
|
+
from .agent import GoLVAgent
|
|
5
|
+
from .exceptions import GoLVError, AuthError, VMNotFoundError, SecurityError
|
|
6
|
+
|
|
7
|
+
class GoLVSetup:
|
|
8
|
+
"""
|
|
9
|
+
Point d'entrée principal du SDK GoLV.
|
|
10
|
+
Permet :
|
|
11
|
+
- Authentification
|
|
12
|
+
- Création de VMConfig
|
|
13
|
+
- Création d'un agent IA
|
|
14
|
+
- Accès au client API
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
api_key: Optional[str] = None,
|
|
20
|
+
base_url: str = "https://golv.onrender.com",
|
|
21
|
+
):
|
|
22
|
+
self.base_url = base_url
|
|
23
|
+
self.api_key = api_key
|
|
24
|
+
|
|
25
|
+
# Client API interne
|
|
26
|
+
self.client = GoLVClient(
|
|
27
|
+
base_url=self.base_url,
|
|
28
|
+
api_key=self.api_key
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# ---------- AUTHENTIFICATION ----------
|
|
32
|
+
|
|
33
|
+
def login(self, username: str, password: str) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Authentifie l'utilisateur et stocke la clé API.
|
|
36
|
+
"""
|
|
37
|
+
token = self.client.authenticate(username, password)
|
|
38
|
+
self.api_key = token
|
|
39
|
+
return token
|
|
40
|
+
|
|
41
|
+
# ---------- CONFIGURATION VM ----------
|
|
42
|
+
|
|
43
|
+
def create_vm_config(
|
|
44
|
+
self,
|
|
45
|
+
name: Optional[str] = None,
|
|
46
|
+
vm_type: VMType = VMType.UBUNTU,
|
|
47
|
+
version: str = "22.04 LTS",
|
|
48
|
+
is_public: bool = False,
|
|
49
|
+
) -> VMConfig:
|
|
50
|
+
"""
|
|
51
|
+
Crée une configuration de VM prête à l'emploi.
|
|
52
|
+
"""
|
|
53
|
+
return VMConfig(
|
|
54
|
+
name=name,
|
|
55
|
+
vm_type=vm_type,
|
|
56
|
+
version=version,
|
|
57
|
+
is_public=is_public
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def create_default_vm(self, name: Optional[str] = None) -> VMConfig:
|
|
61
|
+
"""
|
|
62
|
+
Crée une VM Ubuntu par défaut.
|
|
63
|
+
"""
|
|
64
|
+
return self.create_vm_config(name=name)
|
|
65
|
+
|
|
66
|
+
# ---------- CREATION AGENT ----------
|
|
67
|
+
|
|
68
|
+
def create_agent(
|
|
69
|
+
self,
|
|
70
|
+
vm_config: Optional[VMConfig] = None,
|
|
71
|
+
allowed_commands: Optional[list[str]] = None,
|
|
72
|
+
max_command_length: int = 200,
|
|
73
|
+
timeout: int = 30,
|
|
74
|
+
security_level=None,
|
|
75
|
+
api_key: Optional[str] = None
|
|
76
|
+
) -> GoLVAgent:
|
|
77
|
+
"""
|
|
78
|
+
Crée un agent GoLV sécurisé.
|
|
79
|
+
"""
|
|
80
|
+
agent_config = AgentConfig(
|
|
81
|
+
vm_config=vm_config or self.create_default_vm(),
|
|
82
|
+
allowed_commands=allowed_commands or [],
|
|
83
|
+
max_command_length=max_command_length,
|
|
84
|
+
timeout=timeout,
|
|
85
|
+
security_level=security_level,
|
|
86
|
+
api_key=api_key or self.api_key
|
|
87
|
+
)
|
|
88
|
+
return GoLVAgent(config=agent_config)
|
|
89
|
+
|
|
90
|
+
# ---------- ACCÈS AU CLIENT ----------
|
|
91
|
+
|
|
92
|
+
def get_client(self) -> GoLVClient:
|
|
93
|
+
"""
|
|
94
|
+
Retourne le client API configuré.
|
|
95
|
+
"""
|
|
96
|
+
return self.client
|
|
97
|
+
|
|
98
|
+
def __repr__(self) -> str:
|
|
99
|
+
auth_state = "authenticated" if self.api_key else "unauthenticated"
|
|
100
|
+
return f"<GoLVSetup base_url={self.base_url!r} state={auth_state}>"
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: golv
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: SDK Python pour GoLV - Terminal sécurisé pour IA
|
|
5
|
+
Home-page: https://github.com/gopu-inc/GoLV-VM
|
|
6
|
+
Author: GOPU.inc
|
|
7
|
+
Author-email: ceoseshell@gmail.com
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: requests>=2.28.0
|
|
21
|
+
Requires-Dist: pydantic<2.0,>=1.10
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
24
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
25
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
26
|
+
Provides-Extra: ai
|
|
27
|
+
Requires-Dist: openai>=1.0.0; extra == "ai"
|
|
28
|
+
Requires-Dist: langchain>=0.0.300; extra == "ai"
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: provides-extra
|
|
37
|
+
Dynamic: requires-dist
|
|
38
|
+
Dynamic: requires-python
|
|
39
|
+
Dynamic: summary
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# 🚀 GoLV-VM
|
|
44
|
+
<div align="center">
|
|
45
|
+
|
|
46
|
+

|
|
47
|
+
[](https://vercel.com/mauricio-100s-projects/golvcloud/HUH6zJsuxbyoxNbRkHLFTtjPf8an)
|
|
48
|
+
[](https://pypi.org/project/golv/)
|
|
49
|
+
[](https://www.python.org/)
|
|
50
|
+
[](https://github.com/MauricioKk-ship-it/GoLV-VM/actions)
|
|
51
|
+
[](LICENSE)
|
|
52
|
+
[]()
|
|
53
|
+
|
|
54
|
+
GoLV-VM est un **SDK Python pour la gestion de VMs sécurisées** et l'exécution de commandes via un agent intelligent.
|
|
55
|
+
Il permet de créer, configurer et exécuter des commandes sur des VMs distantes de manière simple et sécurisée, prêt pour l'intégration avec IA et automation.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## ⚡ Features
|
|
60
|
+
|
|
61
|
+
- ✅ Création et gestion de VMs (Ubuntu, Debian, Python-Dev, NodeJS, Docker, Wordpress)
|
|
62
|
+
- ✅ SDK facile à utiliser (`GoLVSetup`)
|
|
63
|
+
- ✅ Agent sécurisé pour exécuter des commandes avec filtrage et sécurité
|
|
64
|
+
- ✅ Support pour exécuter du code Python et des commandes Git
|
|
65
|
+
- ✅ Commandes prédéfinies pour automatiser vos VMs
|
|
66
|
+
- ✅ Gestion des erreurs et sécurité avancée (commandes interdites, longueur maximale, etc.)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 📦 Installation
|
|
71
|
+
|
|
72
|
+
# Cloner le repo
|
|
73
|
+
```bash
|
|
74
|
+
git clone https://github.com/gopu-inc/GoLV-VM.git
|
|
75
|
+
cd GoLV-VM
|
|
76
|
+
|
|
77
|
+
# Installer en mode editable
|
|
78
|
+
pip install -e .
|
|
79
|
+
```
|
|
80
|
+
# via python
|
|
81
|
+
```bash
|
|
82
|
+
pip install golv
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
# 🧰 Usage
|
|
88
|
+
|
|
89
|
+
Initialisation du SDK
|
|
90
|
+
```python
|
|
91
|
+
from golv import GoLVSetup, VMType
|
|
92
|
+
|
|
93
|
+
# Initialiser le SDK
|
|
94
|
+
setup = GoLVSetup(api_key="votre_clef_api")
|
|
95
|
+
client = setup.get_client()
|
|
96
|
+
|
|
97
|
+
# Créer une VM Ubuntu par défaut
|
|
98
|
+
vm_config = setup.create_default_vm("ma-vm")
|
|
99
|
+
vm = client.create_vm(vm_config)
|
|
100
|
+
print("VM créée:", vm)
|
|
101
|
+
|
|
102
|
+
Création d’un agent sécurisé
|
|
103
|
+
|
|
104
|
+
from golv import GoLVSetup
|
|
105
|
+
|
|
106
|
+
setup = GoLVSetup(api_key="votre_clef_api")
|
|
107
|
+
|
|
108
|
+
# Créer un agent avec commandes autorisées
|
|
109
|
+
agent = setup.create_agent(
|
|
110
|
+
allowed_commands=["echo", "python", "git"]
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Exécuter une commande
|
|
114
|
+
result = agent.execute("echo 'Hello GoLV'")
|
|
115
|
+
print(result.output)
|
|
116
|
+
|
|
117
|
+
# Exécuter du code Python
|
|
118
|
+
py_result = agent.execute_python("print('Hello from Python')")
|
|
119
|
+
print(py_result.output)
|
|
120
|
+
|
|
121
|
+
Commandes sécurisées et prédéfinies
|
|
122
|
+
|
|
123
|
+
# Commande prédéfinie (ex: list_files)
|
|
124
|
+
predef = agent.predefined("list_files")
|
|
125
|
+
print(predef.output)
|
|
126
|
+
|
|
127
|
+
# Gestion des erreurs de sécurité
|
|
128
|
+
try:
|
|
129
|
+
agent.execute("rm -rf /")
|
|
130
|
+
except Exception as e:
|
|
131
|
+
print("Sécurité:", e)
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
# 📊 Structure du SDK
|
|
137
|
+
```bash
|
|
138
|
+
golv/
|
|
139
|
+
├── __init__.py # Expose GoLVSetup, Client, Agent, Exceptions
|
|
140
|
+
├── client.py # Client HTTP pour API GoLV
|
|
141
|
+
├── agent.py # Agent sécurisé pour exécution de commandes
|
|
142
|
+
├── models.py # Dataclasses VMConfig, CommandResult, VMType...
|
|
143
|
+
├── exceptions.py # Gestion des erreurs et sécurité
|
|
144
|
+
└── setup_golv.py # Classe GoLVSetup (point d'entrée SDK)
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
# 🛡️ Sécurité
|
|
150
|
+
|
|
151
|
+
Commandes interdites détectées automatiquement (rm -rf, shutdown, etc.)
|
|
152
|
+
|
|
153
|
+
Longueur maximale des commandes configurable
|
|
154
|
+
|
|
155
|
+
Liste blanche de commandes autorisées
|
|
156
|
+
|
|
157
|
+
Agent isolé et sécurisé pour exécution IA
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
# 🧪 Tests
|
|
164
|
+
```bash
|
|
165
|
+
python test_golv_sdk.py
|
|
166
|
+
```
|
|
167
|
+
Ce script teste :
|
|
168
|
+
|
|
169
|
+
Création de VM
|
|
170
|
+
|
|
171
|
+
Agent sécurisé
|
|
172
|
+
|
|
173
|
+
Exécution de commandes (echo, Python, Git)
|
|
174
|
+
|
|
175
|
+
Sécurité et exceptions
|
|
176
|
+
|
|
177
|
+
Commandes prédéfinies
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
# 🔗 Liens
|
|
184
|
+
|
|
185
|
+
[GitHub Repo](https://github.com/gopu-inc/GoLV-VM)
|
|
186
|
+
|
|
187
|
+
[PyPI Package](https://pypi.org/project/golv-py/)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
-
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
# 📄 License
|
|
194
|
+
|
|
195
|
+
MIT © GOPU.inc
|
|
196
|
+
|
|
197
|
+
---
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
golv/__init__.py,sha256=iOULOp1udfTqXB4LF3oysp9Z9gojIoCHIkJLeKD78H8,577
|
|
2
|
+
golv/agent.py,sha256=hufRhrMxHWUnT1o82osVX9UWYncROEAgAEPARHDe8e8,5385
|
|
3
|
+
golv/client.py,sha256=OurQx9TJIHBzHWrvX49Xw0GnPfwzjeWr3uZCBmXJ0QU,6233
|
|
4
|
+
golv/exeptions.py,sha256=C3IFFiZIo4WG1ue2OJ4j6GgBc4hi_d7TfmTH9kUTyfw,370
|
|
5
|
+
golv/models.py,sha256=dgNvAkYCa8pwqyfFXo7pe_Sbzt4f3LEVHySPS9kbGOY,3370
|
|
6
|
+
golv/setup_golv.py,sha256=kSLjsHrpPVPlTOZvn9iHsCZpN5UtVkWuxEfLaGeS-nw,2854
|
|
7
|
+
golv-1.1.0.dist-info/licenses/LICENSE,sha256=1IwxJJBocSzfqZ81NORFCbPvFxycSA_3EDjbbSI2FAM,1065
|
|
8
|
+
golv-1.1.0.dist-info/METADATA,sha256=U7QScbMHViDZBWx5Q35UYAIQIo3TKuQiKsQUrjBNgec,5363
|
|
9
|
+
golv-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
golv-1.1.0.dist-info/entry_points.txt,sha256=-8ULbipT3Yv4LP4mlry0xOs7L-fj4reUfJhZl1KTmRE,40
|
|
11
|
+
golv-1.1.0.dist-info/top_level.txt,sha256=c4_WAPPlpxSRzeHS_wVZFfN9Za_S_gLlEYserQW5_dY,5
|
|
12
|
+
golv-1.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 gopu.inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
golv
|