Skip to content
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

[GT-95] Prepare for API credential management based on renewal time #447

Merged
merged 7 commits into from May 4, 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
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,20 @@ public function __construct($dryRun, $entityManager, $baseTime)
*
* @param int $threshold The number of months of no-use prior to $baseTime to use for selection
*/
public function getCreds($threshold)
public function getCreds($threshold, $propertyName)
{
$qbl = $this->entityManager->createQueryBuilder();

$qbl->select('cred')
->from('APIAuthentication', 'cred')
->where('cred.lastUseTime < :threshold')
->andWhere($qbl->expr()->isNotNull("cred.user")); // cope with legacy entities
->where($qbl->expr()->isNotNull("cred.user")) // cope with legacy entities
->andWhere('cred.' . $propertyName . '< :threshold');

$timeThresh = clone $this->baseTime;

if ($threshold > 0) {
$timeThresh->sub(new DateInterval("P" . $threshold . "M"));
}
};

$qbl->setParameter('threshold', $timeThresh->format('Y-m-d 00:00:00'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* Sender and reply-to email addresses are taken from the local_info.xml config file.
*
* Usage: php ManageAPICredentials.php [ --help | -h ] [ --dry-run ] \\
* Usage: php ManageUnusedAPICredentials.php [ --help | -h ] [ --dry-run ] \\
* [[ --warning_threshold | -w ] LITTLE_MONTHS ] \\
* [[ --deletion_threshold | -d ] BIG_MONTHS ]
*
Expand All @@ -24,7 +24,7 @@

require_once dirname(__FILE__) . "/../../lib/Gocdb_Services/Factory.php";
require_once dirname(__FILE__) . "/ManageAPICredentialsActions.php";
require_once dirname(__FILE__) . "/ManageAPICredentialsOptions.php";
require_once dirname(__FILE__) . "/ManageUnusedAPICredentialsOptions.php";

use DateTime;
use DateTimeZone;
Expand All @@ -41,7 +41,7 @@
$replyToEmail = (string) $configService->getEmailTo();

try {
$options = new ManageAPICredentialsOptions();
$options = new ManageUnusedAPICredentialsOptions();

if ($options->isShowHelp()) {
return;
Expand All @@ -51,7 +51,7 @@

$actions = new ManageAPICredentialsActions($options->isDryRun(), $entityManager, $baseTime);

$creds = $actions->getCreds($options->getThreshold());
$creds = $actions->getCreds($options->getThreshold(), 'lastUseTime');

if ($options->isDeleteEnabled()) {
$creds = $actions->deleteCreds(
Expand All @@ -70,5 +70,5 @@
);
}
} catch (InvalidArgumentException $except) {
ManageAPICredentialsOptions::usage($except->getMessage());
ManageUnusedAPICredentialsOptions::usage($except->getMessage());
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use InvalidArgumentException;

class ManageAPICredentialsOptions
class ManageUnusedAPICredentialsOptions
{
protected $showHelp = false;
protected $warn;
Expand Down
6 changes: 4 additions & 2 deletions tests/DoctrineTestSuite1.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
require_once __DIR__ . '/writeAPI/siteMethods.php';
require_once __DIR__ . '/writeAPI/serviceMethods.php';
require_once __DIR__ . '/writeAPI/endpointMethods.php';
require_once __DIR__ . '/resourcesTests/ManageAPICredentialsTest.php';
require_once __DIR__ . '/resourcesTests/ManageUnusedAPICredentialsTest.php';
require_once __DIR__ . '/resourcesTests/ManageUnrenewedAPICredentialsTest.php';

use PHPUnit_Framework_TestSuite;

Expand Down Expand Up @@ -74,7 +75,8 @@ public static function suite()
$suite->addTestSuite('WriteAPIsiteMethodsTests');
$suite->addTestSuite('WriteAPIserviceMethodsTests');
$suite->addTestSuite('WriteAPIendpointMethodsTests');
$suite->addTestSuite('org\gocdb\tests\ManageAPICredentialsTest');
$suite->addTestSuite('org\gocdb\tests\ManageUnusedAPICredentialsTest');
$suite->addTestSuite('org\gocdb\tests\ManageUnrenewedAPICredentialsTest');


return $suite;
Expand Down
66 changes: 66 additions & 0 deletions tests/resourcesTests/ManageAPICredentialsTestUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* Helper functions for API credential management scripts
*/

namespace org\gocdb\tests;

require_once __DIR__ . '/../unit/lib/Gocdb_Services/ServiceTestUtil.php';

use DateInterval;
use DateTime;
use DateTimeZone;
use org\gocdb\tests\ServiceTestUtil;

class ManageAPICredentialsTestUtils
{
private $serviceTestUtil;
private $entityManager;

public function __construct($entityManager)
{
$this->entityManager = $entityManager;
$this->serviceTestUtil = new ServiceTestUtil();
}
/**
* Create a number of unique API authentication credentials, evenly spaced each
* with last used time and last renewed time a given number of months before the
* previous, starting the given number of months before the current time.
*
* @param integer $number The number of credentials to create
* @param integer $intervalMonths The interval in months between credentials used to
* set lastUseTime and lastRenewTime
* @return \DateTime Time used as base: the first credential will have time values
* $intervalMonths older than this
*/
public function createTestAuthEnts($number, $intervalMonths)
{
list($user, $site, $siteService) =
$this->serviceTestUtil->createGocdbEntities($this->entityManager);

$baseTime = new DateTime('now', new DateTimeZone('UTC'));

$type = 'X.509';

$time = clone $baseTime;

for ($count = 1; $count <= $number; $count++) {
// $useTime will be decremented by 6M for each loop
$time->sub(new DateInterval('P' . $intervalMonths . 'M'));
$ident = '/CN=A Dummy Subject ' . $count;
$authEnt = $siteService->addAPIAuthEntity(
$site,
$user,
array(
'IDENTIFIER' => $ident,
'TYPE' => $type,
'ALLOW_WRITE' => false
)
);
$authEnt->setLastUseTime($time);
$authEnt->setLastRenewTime($time);
}
return $baseTime;
}
}
167 changes: 167 additions & 0 deletions tests/resourcesTests/ManageUnrenewedAPICredentialsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

/*
* Copyright (C) 2015 STFC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace org\gocdb\tests;

use org\gocdb\scripts\ManageAPICredentialsActions;
use org\gocdb\tests\ManageAPICredentialsTestUtils;
use PHPUnit_Extensions_Database_Operation_Factory;
use PHPUnit_Extensions_Database_TestCase;

require_once __DIR__ . '/ManageAPICredentialsTestUtils.php';
require_once __DIR__ . '/../unit/lib/Gocdb_Services/ServiceTestUtil.php';
require_once __DIR__ . '/../../resources/ManageAPICredentials/ManageAPICredentialsActions.php';

class ManageUnrenewedAPICredentialsTest extends PHPUnit_Extensions_Database_TestCase
{
private $entityManager;
private $dbOpsFactory;

public function __construct()
{
parent::__construct();
// Use a local instance to avoid Mess Detector's whinging about avoiding
// static access.
$this->dbOpsFactory = new PHPUnit_Extensions_Database_Operation_Factory();
}
/**
* Overridden.
*/
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
echo "\n\n-------------------------------------------------\n";
echo "Executing ManageUnrenewedAPICredentialsTest. . .\n";
}
/**
* Overridden. Returns the test database connection.
* @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
require_once __DIR__ . '/../doctrine/bootstrap_pdo.php';
return getConnectionToTestDB();
}
/**
* Overridden. Returns the test dataset.
* Defines how the initial state of the database should look before each test is executed.
* @return PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
$dataset = $this->createFlatXMLDataSet(__DIR__ . '/../doctrine/truncateDataTables.xml');
return $dataset;
// Use below to return an empty data set if we don't want to truncate and seed
//return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet();
}
/**
* Overridden.
*/
protected function getSetUpOperation()
{
// CLEAN_INSERT is default
//return PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT();
//return PHPUnit_Extensions_Database_Operation_Factory::UPDATE();
//return PHPUnit_Extensions_Database_Operation_Factory::NONE();
//
// Issue a DELETE from <table> which is more portable than a
// TRUNCATE table <table> (some DBs require high privileges for truncate statements
// and also do not allow truncates across tables with FK contstraints e.g. Oracle)
return $this->dbOpsFactory->DELETE_ALL();
}
/**
* Overridden.
*/
protected function getTearDownOperation()
{
// NONE is default
return $this->dbOpsFactory->NONE();
}
/**
* Sets up the fixture, e.g create a new entityManager for each test run
* This method is called before each test method is executed.
*/
protected function setUp()
{
parent::setUp();
$this->entityManager = $this->createEntityManager();
// Pass the Entity Manager into the Factory to allow Gocdb_Services
// to use other Gocdb_Services.
\Factory::setEntityManager($this->entityManager);

date_default_timezone_set("UTC");
}
/**
* Run after each test function to prevent pile-up of database connections.
*/
protected function tearDown()
{
parent::tearDown();
if (!is_null($this->entityManager)) {
$this->entityManager->getConnection()->close();
}
}
/**
* @return EntityManager
*/
private function createEntityManager()
{
$entityManager = null; // Initialise in local scope to avoid unused variable warnings
require __DIR__ . '/../doctrine/bootstrap_doctrine.php';
return $entityManager;
}
public function testLastRenewTime()
{
print __METHOD__ . "\n";

// Create 8 credentials, each 2 month apart.
// 2 months chosen so the exact definition of a month doesn't matter.
$utils = new ManageAPICredentialsTestUtils($this->entityManager);
$baseTime = $utils->createTestAuthEnts(8, 2);

$entityManager = $this->createEntityManager();

$actions = new ManageAPICredentialsActions(false, $entityManager, $baseTime);

// Fetch credentials not renewed in the last 5 months - should be 6.
$creds = $actions->getCreds(5, 'lastRenewTime');

$this->assertCount(
6,
$creds,
'Failed to filter credentials based on last renew time.'
);

// remove credentials last renewed more than 9 months ago
// there should be 2 left after this operation (as 2 of
// the 6 fetched above have been renewed with 9 months).
$creds = $actions->deleteCreds($creds, 9);

$this->assertCount(
2,
$creds,
'Failed to delete credential by renew time.'
);

// If we now repeat the original query there should be just 4
// credential following the delete.
$creds = $actions->getCreds(5, 'lastRenewTime');

$this->assertCount(
2,
$creds,
'Unexpected credential count following deletion.'
);
}
}
Loading