Skip to content

Commit

Permalink
- Replaced pve2-api-php with fork that uses symfony & httpclient.
Browse files Browse the repository at this point in the history
- Reworked some of the server preparation functionality
- Added "Debug mode" to proxmox Settings
  • Loading branch information
Chris Schläpfer committed Sep 29, 2023
1 parent 96e963d commit abbc2ce
Show file tree
Hide file tree
Showing 9 changed files with 590 additions and 663 deletions.
34 changes: 28 additions & 6 deletions Api/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,17 @@ public function server_create($data)
'ipv4' => 'Server ipv4 is missing',
'hostname' => 'Server hostname is missing',
'port' => 'Server port is missing',
'root_user' => 'Root user is missing',
'root_password' => 'Root password is missing',
'auth_type' => 'Authentication type is missing',
'realm' => 'Proxmox user realm is missing',
);
$this->di['validator']->checkRequiredParamsForArray($required, $data);

// check if server already exists based on name, ipv4 or hostname
$server = $this->di['db']->findOne('service_proxmox_server', 'name=:name OR ipv4=:ipv4 OR hostname=:hostname', array(':name' => $data['name'], ':ipv4' => $data['ipv4'], ':hostname' => $data['hostname']));
if ($server) {
throw new \Box_Exception('Server already exists');
}

$server = $this->di['db']->dispense('service_proxmox_server');
$server->name = $data['name'];
$server->group = $data['group'];
Expand All @@ -416,17 +421,34 @@ public function server_create($data)
$server->hostname = $data['hostname'];
$server->port = $data['port'];
$server->realm = $data['realm'];
$server->root_user = $data['root_user'];
$server->root_password = $data['root_password'];
$server->active = $data['active'];
$server->created_at = date('Y-m-d H:i:s');
$server->updated_at = date('Y-m-d H:i:s');

$this->di['db']->store($server);

$this->di['logger']->info('Created Proxmox server %s', $server->id);

// check if auth_type is username or token
if ($data['auth_type'] == 'username') {
$server->root_user = $data['root_user'];
$server->root_password = $data['root_password'];
$server->tokenname = '';
$server->tokenvalue = '';
$this->di['db']->store($server);
$this->getService()->test_connection($server);
} else {
$server->root_user = '';
$server->root_password = '';
$server->tokenname = $data['tokenname'];
$server->tokenvalue = $data['tokenvalue'];
$this->di['db']->store($server);

}


// Validate server by testing connection
$this->getService()->test_connection;



return true;
}
Expand Down
174 changes: 96 additions & 78 deletions ProxmoxAuthentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ trait ProxmoxAuthentication
*/
public function prepare_pve_setup($server)
{
$config = $this->di['mod_config']('Serviceproxmox');
// Retrieve the server access information
$serveraccess = $this->find_access($server);

// Create a new instance of the PVE2_API class with the server access details
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue);
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue, debug: $config['pmx_debug_logging']);

// Attempt to log in to the server using the API
if (!$proxmox->login()) {
Expand Down Expand Up @@ -82,85 +83,101 @@ public function prepare_pve_setup($server)
default:
throw new \Box_Exception("More than one group found");
break;
}
}

}


// Validate if there already is a user and token for fossbilling
$users = $proxmox->get("/access/users");
$found = 0;
// Iterate through the users and check for a user beginning with 'fb'
foreach ($users as $user) {
if (strpos($user['userid'], 'fb') === 0) {
$found += 1;
$userid = $user['userid'];
}
// Handle the cases where there are no users, one user, or multiple users
switch ($found) {
case 0:
// Create a new user
$userid = 'fb_' . rand(1000, 9999) . '@pve'; // TODO: Make realm configurable in the module settings
$newuser = $proxmox->post("/access/users", array('userid' => $userid, 'password' => $this->di['tools'], 'enable' => 1, 'comment' => 'fossbilling user', 'groups' => $groupid));

// Create a token for the new user
$token = $proxmox->post("/access/users/" . $userid . "/token/fb_access", array());

// Check if the token was created successfully
if ($token) {
$server->tokenname = $token['full-tokenid'];
$server->tokenvalue = $token['value'];
} else {
throw new \Box_Exception("Failed to create token for fossbilling user");
// Validate if there already is a user and token for fossbilling
$users = $proxmox->get("/access/users");
$found = 0;
// Iterate through the users and check for a user beginning with 'fb'
foreach ($users as $user) {
if (strpos($user['userid'], 'fb') === 0) {
$found += 1;
$userid = $user['userid'];
}
// Handle the cases where there are no users, one user, or multiple users
switch ($found) {
case 0:
// Create a new user
$userid = 'fb_' . rand(1000, 9999) . '@pve'; // TODO: Make realm configurable in the module settings
$newuser = $proxmox->post("/access/users", array('userid' => $userid, 'password' => $this->di['tools'], 'enable' => 1, 'comment' => 'fossbilling user', 'groups' => $groupid));

// Create a token for the new user
$token = $proxmox->post("/access/users/" . $userid . "/token/fb_access", array());

// Check if the token was created successfully
if ($token) {
$server->tokenname = $token['full-tokenid'];
$server->tokenvalue = $token['value'];
} else {
throw new \Box_Exception("Failed to create token for fossbilling user");
break;
}
break;
}
break;
case 1:
// Create a token for the existing user
$token = $proxmox->post("/access/users/" . $userid . "/token/fb_access", array());
if ($token) {
$server->tokenname = $token['full-tokenid'];
$server->tokenvalue = $token['value'];
} else {
throw new \Box_Exception("Failed to create token for fossbilling user");
case 1:
// Create a token for the existing user
$token = $proxmox->post("/access/users/" . $userid . "/token/fb_access", array());
if ($token) {
$server->tokenname = $token['full-tokenid'];
$server->tokenvalue = $token['value'];
} else {
throw new \Box_Exception("Failed to create token for fossbilling user");
break;
}
break;
default:
throw new \Box_Exception("There are more than one fossbilling users on the server. Please delete all but one.");
break;
}
// Create permissions for the newly created token
// Set up permissions for the token (Admin user) to manage users, groups, and other administrative tasks
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEUserAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEAuditor', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVESysAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEPoolAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEDatastoreAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEUserAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEAuditor', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVESysAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEPoolAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEDatastoreAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));

// Sleep for 5 seconds
sleep(5);

// Check if the permissions were created correctly by logging in and creating another user
/*
echo "<script>console.log('".json_encode($serveraccess)."');</script>";
echo "<script>console.log('".json_encode($userid)."');</script>";
echo "<script>console.log('".json_encode($server->realm)."');</script>";
echo "<script>console.log('".json_encode($server->tokenname)."');</script>";
echo "<script>console.log('".json_encode($server->tokenvalue)."');</script><br /><br />";
*/

// Delete the root password and unset the PVE2_API instance
$server->root_password = null;
unset($proxmox);

// Return the test_access result for the server
return $this->test_access($server);
}
} else {
// Validate Permissions for the token
$permissions = $proxmox->get("/access/acl/");
// Check for 'PVEUserAdmin', 'PVEAuditor', 'PVESysAdmin', 'PVEPoolAdmin', and 'PVEDatastoreAdmin' permissions, and if they don't exist, try to create them.
$required_permissions = array('PVEUserAdmin', 'PVEAuditor', 'PVESysAdmin', 'PVEPoolAdmin', 'PVEDatastoreAdmin');
foreach ($required_permissions as $permission) {
$found_permission = 0;
foreach ($permissions as $acl) {
if ($acl['roleid'] == $permission) {
$found_permission += 1;
}
break;
default:
throw new \Box_Exception("There are more than one fossbilling users on the server. Please delete all but one.");
break;
}
if (!$found_permission) {
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => $permission, 'propagate' => 1, 'tokens' => $server->tokenname));
}
}
// Create permissions for the newly created token
// Set up permissions for the token (Admin user) to manage users, groups, and other administrative tasks
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEUserAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEAuditor', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVESysAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEPoolAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEDatastoreAdmin', 'propagate' => 1, 'users' => $userid));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEUserAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEAuditor', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVESysAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEPoolAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));
$permissions = $proxmox->put("/access/acl/", array('path' => '/', 'roles' => 'PVEDatastoreAdmin', 'propagate' => 1, 'tokens' => $server->tokenname));

// Sleep for 5 seconds
sleep(5);

// Check if the permissions were created correctly by logging in and creating another user
/*
echo "<script>console.log('".json_encode($serveraccess)."');</script>";
echo "<script>console.log('".json_encode($userid)."');</script>";
echo "<script>console.log('".json_encode($server->realm)."');</script>";
echo "<script>console.log('".json_encode($server->tokenname)."');</script>";
echo "<script>console.log('".json_encode($server->tokenvalue)."');</script><br /><br />";
*/

// Delete the root password and unset the PVE2_API instance
$server->root_password = null;
unset($proxmox);

// Return the test_access result for the server
return $this->test_access($server);

}
}

Expand All @@ -176,9 +193,9 @@ public function test_access($server)
{
// Retrieve the server access information
$serveraccess = $this->find_access($server);

$config = $this->di['mod_config']('Serviceproxmox');
// Create a new instance of the PVE2_API class with the server access details
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue);
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue, debug: $config['pmx_debug_logging']);

// Attempt to log in to the server using the API
if (!$proxmox->login()) {
Expand All @@ -189,7 +206,7 @@ public function test_access($server)
$userid = 'tfb_' . rand(1000, 9999) . '@pve'; // TODO: Make realm configurable in the module settings

// Create a new user for testing purposes
$newuser = $proxmox->post("/access/users", array('userid' => $userid, 'password' => $this->di['tools']->generatePassword(16, 4), 'enable' => '1', 'comment' => 'fossbilling user 2'));
$proxmox->post("/access/users", array('userid' => $userid, 'password' => $this->di['tools']->generatePassword(16, 4), 'enable' => '1', 'comment' => 'FOSSBilling test user ' . $userid));

// Retrieve the newly created user
$newuser = $proxmox->get("/access/users/" . $userid);
Expand Down Expand Up @@ -227,7 +244,8 @@ public function create_client_user($server, $client)
$clientuser->client_id = $client->id;
$this->di['db']->store($clientuser);
$serveraccess = $this->find_access($server);
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue);
$config = $this->di['mod_config']('Serviceproxmox');
$proxmox = new PVE2_API($serveraccess, $server->root_user, $server->realm, $server->root_password, port: $server->port, tokenid: $server->tokenname, tokensecret: $server->tokenvalue, debug: $config['pmx_debug_logging']);
if (!$proxmox->login()) {
throw new \Box_Exception("Failed to connect to the server. create_client_user");
}
Expand Down
Loading

0 comments on commit abbc2ce

Please sign in to comment.