Desarrollando y automatizando vía API de cPanel

La API de cPanel es una gran desconocida para el usuario final, a día de hoy esta interfaz da acceso a absolutamente todas las funciones de cPanel, permitiendo controlar y automatizar cualquier necesidad que se tenga, desde aquellas más básicas como crear cuentas de correo desde una herramienta externa (por ejemplo para facilitar el onboarding de nuevos usuarios o empleados), crear redirecciones, copias de seguridad, obtener estadísticas y en general cualquier función que necesites.

Esta API tiene la versatilidad de permitir el acceso por diferentes vías, por ejemplo a nivel local se puede usar vía SSH sin requerir autenticación de ningún tipo, o haciendo llamadas (ej desde cURL o un cliente http) a la URL de cPanel usando autenticación vía token.

Aunque la API de cPanel cuenta con una extensa documentación, para reducir las barreras de entrada, vamos a mostrar varios ejemplos prácticos para las diferentes formas de autenticación y uso.

Acceso a la API vía terminal, comando uapi

Si el uso de la API será desde el propio servidor que aloja la cuenta, cPanel no requerirá ningún tipo de autenticación, pudiendo hacer uso de forma libre de la API.

Ejemplo de uso, creando una redirección vía terminal

Si tienes experiencia con el uso de SSH y línea de comandos, esta vía es probablemente la más rápida para embarcarte en el uso de la API, para ello dispondríamos del comando uapi que hace de punto de entrada.

En este caso ejemplo vamos a añadir una redirección para uno de los dominios configurados, esto lo haremos por medio de la llamada Mime add_redirect.

Siguiendo con el ejemplo, si queremos redireccionar dominio1.com a dominio2.com, con una redirección de tipo 301 (permanente) tanto para www como sin estas, los parámetros necesarios serían que deberemos transmitir a la llamada a la API serían:

  • domain: dominio1.com
  • redirect: https://dominio2.com
  • type: permanent
  • redirect_www: 0

Con lo que el comando a ejecutar quedaría de la siguiente forma:

uapi --output=jsonpretty \
  Mime \
  add_redirect \
  domain='example.com' \
  redirect='http://example.com/' \
  redirect_www=0 \
  type="permanent"

Tras ejecutar el comando recibiremos confirmación en formato json tabulado (jsonpretty), informando si se añadió correctamente o de cualquier error que pudiese ocurrir.

En el valor de --output= definimos en que formato queremos la respuesta, puede ser json, jsonpretty o yaml

Ejemplo de uso, obteniendo un listado de cuentas de correo

Lo primero sería localizar la función que necesitamos para obtener el listado de todas las cuentas de correo existentes en nuestro servicio, para ello usaremos Email list_pops, que tal como indica la documentación, devuelve un listado de todos los emails.

Ejecutar esta operación es tan fácil como ejecutar uapi Email list_pops obteniendo un resultado tipo:

apiversion: 3
func: list_pops
module: Email
result:
  data:
    -
      email: account@domain.com
      login: Main Account
      suspended_incoming: 0
      suspended_login: 0
  errors: ~
  messages: ~
  metadata:
    transformed: 1
  status: 1
  warnings: ~

Dado que queremos un listado de las cuentas y en la respuesta tenemos información que en este caso práctico no necesitamos, podemos combinar varios filtros para limpiar el resultado:

uapi Email list_pops | grep email | awk -F ":" '{print $2}'| sed 's/^[[:space:]]*//'

Este comando devolvería el listado de cuentas de correo, uno por línea y sin más información de la respuesta de la API, en la primera parte ejecutamos la llamada a la API, y el resultado lo filtramos para los campos que aparezca "email", por último con la ayuda de los comandos awk y sed, limpiamos la salida, con lo que tendríamos.

cuenta1@dominio.com
cuenta2@dominio.com
cuenta3@dominio.com

Si queremos guardar el listado en un fichero, simplemente añadimos al final del comando > fichero.txt, esta adición redirecciona la salida para que en vez de en pantalla se envíe a un fichero.txt (si el fichero no existe es creado automáticamente).

El uso de la API por medio del comando uapi es bastante sencillo a la vez que pontente, incluso si tenemos programas en el servidor, podrían usar estos comandos haciendo la llamada desde PHP por medio de una función como shell_exec.

Autenticación con la API desde servidor externo

Para acceder a la API desde un servidor externo, deberemos autenticarnos para que la operación sea permitida por el servidor, para ello necesitaremos un token de acceso.

Los token se pueden crear y gestionar desde cPanel, sección Manage API tokens, se indica un nombre y si el token deberá expirar en algún momento o por el contrario sería permanente (aún no teniendo vencimiento, podrás eliminarlo si lo necesitas).

El sistema generará una cadena de texto aleatoria que sería el token, ten en cuenta que debes anotarlo ya que solo se mostrará una única vez, de igual forma tienes que tener especial cuidado en su custodia, si un atacante tiene acceso a este token, tendrá acceso a toda tu cuenta.

Ya con nuestro token a buen recaudo, podremos hacer llamadas a la API, un ejemplo usando el comando curl:

curl -H'Authorization: cpanel username:APITOKEN' \
'https://example.com:2083/execute/Module/function?parameter=value'
  • username: sería tu usuario de cPanel.
  • APITOKEN: el token que hemos creado.
  • example.com: tu dominio, puede ser cualquiera de los dominios alojados en tu cuenta.

Puedes ver que el formato de la dirección que continúa es execute/Module/function?parameter=value, seguiría la siguiente sintaxis:

  • Module: el módulo de la llamada a la API
  • function: la función de la llamada a la API.
  • parameter: sería cualquier parámetro que queramos pasar a la llamada, siguiendo el formato parameter=value y encadenando varios con &.

Tomando el ejemplo anterior del listado de cuentas de correo vemos que la documentación indica que la llamada de tipo GET se debe realizar sobre /Email/list_pops y que no requiere ningún parámetro adicional obligatorio, por lo que la URL a la que llamar quedaría de la siguiente forma:

https://tudominio.com:2083/execute/Email/list_pops

Ejemplo de uso, vaciando la bandeja de SPAM

Continuando con los ejemplos, queremos automatizar el vaciado de la bandeja de SPAM de todas nuestras cuentas de correo, buscando en la API damos con la operación clear_spam_box que hace exactamente esto, y nos indica que debemos hacer una llamada de tipo GET hacia /SpamAssassin/clear_spam_box.

Siguiendo el ejemplo anterior la llamada usando cURL sería (para las pruebas recomendamos usar un cliente REST como Insomnia):

curl -H'Authorization: cpanel username:APITOKEN' \
'https://example.com:2083/execute/SpamAssassin/clear_spam_box'

Esta misma llamada desde cPanel se podría realizar de la siguiente forma:

$username = "USUARIO_CPANEL";
$token = "TOKEN";
$domain = "DOMINIOCPANEL.COM";
 
$query = 'https://'.$domain.':2083/execute/SpamAssassin/clear_spam_box';
 
$curl = curl_init();                          
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);    
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,0);      
curl_setopt($curl, CURLOPT_HEADER,0);               
curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);       
$header[0] = "Authorization: cpanel " . $username.":".$token . "\n\r";
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);    
curl_setopt($curl, CURLOPT_URL, $query);          
$result = curl_exec($curl);
if ($result == false) {
    error_log("curl_exec threw error \"" . curl_error($curl) . "\" for $query");   
                                                   
}
curl_close($curl);
 
print $result;

Si usas un framework PHP o composer, tienes accesos a librerías como Guzzle que simplifican las llamadas GET y POST, en nuestro caso usamos Laravel por lo que continuaremos los ejemplos haciendo uso de su cliente HTTP.

use Illuminate\Support\Facades\Http;

$username = "CPANEL_USUARIO";
$token = "TOKEN";
$domain = "DOMINIO";
 
$url = 'https://'.$domain.':2083/execute/SpamAssassin/clear_spam_box';
$response = Http::withToken($username . ':' . $token, 'cpanel')->get($url);
$response->json();

Ejemplo de uso, listando las cuentas FTP desde PHP

Si queremos obtener un listado de las cuentas FTP creadas, tras indagar en la documentación damos con /Ftp/list_ftp, por lo que nuestro ejemplo anterior nos valdría para hacer la llamada desde Laravel, modificando la url:

use Illuminate\Support\Facades\Http;

$username = "CPANEL_USUARIO";
$token = "TOKEN";
$domain = "DOMINIO";
 
$url = 'https://'.$domain.':2083/execute/Ftp/list_ftp';
$response = Http::withToken($username . ':' . $token, 'cpanel')->get($url);
$response->json();

Ejemplo de uso, creando cuenta de correo desde PHP

La creación de una cuenta de correo se realizaría usando /Email/add_pop, de nuevo se trata de una llamada vía GET, pero tenemos que pasar una serie de parámetros, concretamente el email que queremos crear y por otro lado, la contraseña que le asignaremos.

use Illuminate\Support\Facades\Http;

$username = "CPANEL_USUARIO";
$token = "TOKEN";
$domain = "DOMINIO";
 
$url = 'https://'.$domain.':2083/execute/Ftp/list_ftp';
$url .= '?email=cuenta@tudominio.com&password=contraseña';
$response = Http::withToken($username . ':' . $token, 'cpanel')->get($url);
$response->json();

Como puedes ver, hemos concatenado en la variable url los parámetros adicionales que se requieren, email y contraseña.

Los expuestos son ejemplos básicos para que puedas familiarizarte con rapidez con la API de cPanel, no obstante todas las llamadas se pueden combinar formando flujos complejos para automatizar tareas tediosas, o incluso integrar con otros programas de los que disponga la empresa o startup.