<?php declare(strict_types = 1); /* ** Zabbix ** Copyright (C) 2001-2022 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ /** * A class for loading secrets from HashiCorp Vault secret manager. */ class CVaultCyberArk extends CVault { public const NAME = 'CyberArk'; public const API_ENDPOINT_DEFAULT = 'https://localhost:1858'; public const DB_PATH_PLACEHOLDER = 'AppID=foo&Query=Safe=bar;Object=buzz'; public const MACRO_PLACEHOLDER = 'AppID=foo&Query=Safe=bar;Object=buzz:key'; /** * @var string */ protected $api_endpoint; /** * @var string */ protected $db_path; /** * @var string */ protected $cert_file; /** * @var string */ protected $key_file; public function __construct(string $api_endpoint, string $db_path, ?string $cert_file, ?string $key_file) { $this->api_endpoint = rtrim(trim($api_endpoint), '/').'/AIMWebService/api/Accounts'; $this->db_path = trim($db_path); $this->cert_file = $cert_file !== null ? trim($cert_file) : null; $this->key_file = $key_file !== null ? trim($key_file) : null; } public function validateParameters(): bool { $api_endpoint = parse_url($this->api_endpoint); if (!array_key_exists('scheme', $api_endpoint) || !array_key_exists('host', $api_endpoint) || strtolower($api_endpoint['scheme']) !== 'https' || $api_endpoint['host'] === '') { $this->addError(_s('Provided API endpoint "%1$s" is invalid.', $this->api_endpoint)); } $secret_parser = new CVaultSecretParser(['provider' => ZBX_VAULT_TYPE_CYBERARK, 'with_key' => false]); if ($secret_parser->parse($this->db_path) != CParser::PARSE_SUCCESS) { $this->addError(_s('Invalid parameter "%1$s": %2$s.', $this->db_path, $secret_parser->getError())); } return !$this->getErrors(); } public function getCredentials(): ?array { $http_context = [ 'method' => 'GET', 'header' => 'Content type: application/json', 'ignore_errors' => true ]; if ($this->cert_file !== null && $this->key_file !== null) { $http_context['ssl'] = [ 'local_cert' => $this->cert_file, 'local_pk' => $this->key_file, 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ]; } $secret = @file_get_contents(urlencode($this->api_endpoint.'?'.$this->db_path), false, stream_context_create(['http' => $http_context]) ); if ($secret === false) { $this->addError(_('Vault connection failed.')); return null; } $db_credentials = $secret ? json_decode($secret, true) : null; if ($db_credentials === null) { $this->addError(_('Unable to load database credentials from Vault.')); return null; } if (!array_key_exists('UserName', $db_credentials) || !array_key_exists('Content', $db_credentials)) { $this->addError(_('Username and password must be stored in Vault secret keys "UserName" and "Content".')); return null; } return [ 'user' => $db_credentials['UserName'], 'password' => $db_credentials['Content'] ]; } }