Skip to content

Define log location; mask API credentials #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions src/ConvertKit_API.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ class ConvertKit_API
/**
* Constructor for ConvertKitAPI instance
*
* @param string $api_key ConvertKit API Key.
* @param string $api_secret ConvertKit API Secret.
* @param boolean $debug Log requests to debugger.
* @param string $api_key ConvertKit API Key.
* @param string $api_secret ConvertKit API Secret.
* @param boolean $debug Log requests to debugger.
* @param string $debugLogFileLocation Path and filename of debug file to write to.
*/
public function __construct(string $api_key, string $api_secret, bool $debug = false)
public function __construct(string $api_key, string $api_secret, bool $debug = false, string $debugLogFileLocation = '')
{
$this->api_key = $api_key;
$this->api_secret = $api_secret;
Expand All @@ -97,8 +98,13 @@ public function __construct(string $api_key, string $api_secret, bool $debug = f
);

if ($debug) {
// If no debug log file location specified, define a default.
if (empty($debugLogFileLocation)) {
$debugLogFileLocation = __DIR__ . '/logs/debug.log';
}

$this->debug_logger = new Logger('ck-debug');
$stream_handler = new StreamHandler(__DIR__ . '/logs/debug.log', Logger::DEBUG);
$stream_handler = new StreamHandler($debugLogFileLocation, Logger::DEBUG);
$this->debug_logger->pushHandler(
$stream_handler // phpcs:ignore Squiz.Objects.ObjectInstantiation.NotAssigned
);
Expand All @@ -114,9 +120,25 @@ public function __construct(string $api_key, string $api_secret, bool $debug = f
*/
private function create_log(string $message)
{
if ($this->debug) {
$this->debug_logger->info($message);
// Don't log anything if debugging isn't enabled.
if (!$this->debug) {
return;
}

// Mask the API Key and Secret.
$message = str_replace(
$this->api_key,
str_repeat('*', (strlen($this->api_key) - 4)) . substr($this->api_key, - 4),
$message
);
$message = str_replace(
$this->api_secret,
str_repeat('*', (strlen($this->api_secret) - 4)) . substr($this->api_secret, - 4),
$message
);

// Add to log.
$this->debug_logger->info($message);
}

/**
Expand Down
69 changes: 69 additions & 0 deletions tests/ConvertKitAPITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,75 @@ public function testDebugEnabled()
$this->assertStringContainsString('ck-debug.INFO: Finish request successfully', $this->getLogFileContents());
}

/**
* Test that debug logging works when enabled, a custom debug log file and path is specified
* and an API call is made.
*
* @since 1.3.0
*
* @return void
*/
public function testDebugEnabledWithCustomLogFile()
{
// Define custom log file location.
$this->logFile = dirname(dirname(__FILE__)) . '/src/logs/debug-custom.log';

// Setup API with debugging enabled.
$api = new \ConvertKit_API\ConvertKit_API(
$_ENV['CONVERTKIT_API_KEY'],
$_ENV['CONVERTKIT_API_SECRET'],
true,
$this->logFile
);
$result = $api->get_account();

// Confirm log file exists.
$this->assertFileExists($this->logFile);

// Confirm that the log includes expected data.
$this->assertStringContainsString('ck-debug.INFO: GET account', $this->getLogFileContents());
$this->assertStringContainsString('ck-debug.INFO: Finish request successfully', $this->getLogFileContents());
}

/**
* Test that debug logging works when enabled and an API call is made, with the API Key and Secret
* masked in the log file.
*
* @since 1.3.0
*
* @return void
*/
public function testDebugAPIKeyAndSecretAreMasked()
{
// Setup API with debugging enabled.
$api = new \ConvertKit_API\ConvertKit_API($_ENV['CONVERTKIT_API_KEY'], $_ENV['CONVERTKIT_API_SECRET'], true);

// Make requests that utilizes both the API Key and Secret.
$api->get_forms(); // API Key.
$api->get_account(); // API Secret.

// Define masked versions of API Key and Secret that we expect to see in the log file.
$maskedAPIKey = str_replace(
$_ENV['CONVERTKIT_API_KEY'],
str_repeat('*', strlen($_ENV['CONVERTKIT_API_KEY']) - 4) . substr($_ENV['CONVERTKIT_API_KEY'], - 4),
$_ENV['CONVERTKIT_API_KEY']
);
$maskedAPISecret = str_replace(
$_ENV['CONVERTKIT_API_SECRET'],
str_repeat('*', strlen($_ENV['CONVERTKIT_API_SECRET']) - 4) . substr($_ENV['CONVERTKIT_API_SECRET'], - 4),
$_ENV['CONVERTKIT_API_SECRET']
);


// Confirm that the log includes the masked API Key and Secret.
$this->assertStringContainsString($maskedAPIKey, $this->getLogFileContents());
$this->assertStringContainsString($maskedAPISecret, $this->getLogFileContents());

// Confirm that the log does not include the unmasked API Key and Secret.
$this->assertStringNotContainsString($_ENV['CONVERTKIT_API_KEY'], $this->getLogFileContents());
$this->assertStringNotContainsString($_ENV['CONVERTKIT_API_SECRET'], $this->getLogFileContents());
}

/**
* Test that debug logging is not performed when disabled and an API call is made.
*
Expand Down