diff --git a/test/functional/pdo_sqlsrv/MsCommon.inc b/test/functional/pdo_sqlsrv/MsCommon.inc index cddfdab9..b1c479e9 100644 --- a/test/functional/pdo_sqlsrv/MsCommon.inc +++ b/test/functional/pdo_sqlsrv/MsCommon.inc @@ -8,30 +8,6 @@ */ -// -// looks like an additional file (in addition to pdo_test_base.inc) may be needed for these PHPTs -// to be runnable from the MSSQL teams' internal proprietary test running system -// - -function IsAEQualified($conn) -{ - $msodbcsql_ver = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)["DriverVer"]; - $msodbcsql_maj = explode(".", $msodbcsql_ver)[0]; - if ($msodbcsql_maj < 17) { - return false; - } - require 'MsSetup.inc'; - if ($daasMode) { - // running against Azure - return true; - } - // if not Azure, check the server version - $server_ver = $conn->getAttribute(PDO::ATTR_SERVER_VERSION); - if (explode('.', $server_ver)[0] < 13) - return false; - return true; -} - // TO BE DELETED function connect($options=array()) { @@ -40,7 +16,7 @@ function connect($options=array()) // simply use $databaseName from MsSetup.inc to facilitate testing in Azure, // which does not support switching databases require 'MsSetup.inc'; - $conn = new PDO( "sqlsrv:Server=$server;database=$databaseName;ConnectionPooling=false;" , $uid, $pwd, $options); + $conn = new PDO( "sqlsrv:Server=$server;database=$databaseName;Driver=$driver;ConnectionPooling=false;" , $uid, $pwd, $options); $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); return $conn; } @@ -58,138 +34,6 @@ function connect($options=array()) } } - -/** - * Connect to the database specified in MsSetup.inc; Column Encryption keywords automatically added when $keystore is not none - * @param string $keywords : string to append to the dsn string in PDO::_construct - * @param array $options : attributes to pass to PDO::_construct - * @param bool $disableCE : flag for disabling column encryption even when keystore is NOT none - * for testing fetching encrypted data when connection column encryption is off - * @return PDO connection object - */ -function ae_connect( $keywords='', $options=array(), $disableCE = false ) -{ - try - { - // simply use $databaseName from MsSetup.inc to facilitate testing in Azure, - // which does not support switching databases - require 'MsSetup.inc'; - $dsn = "sqlsrv:Server=$server;database=$databaseName;ConnectionPooling=false;"; - if ( $keystore != "none" && !$disableCE ) - { - $dsn .= "ColumnEncryption=Enabled;"; - } - if ( $keystore == "ksp" && !$disableCE ) - { - require( 'AE_Ksp.inc' ); - $ksp_path = getKSPPath(); - $dsn .= "CEKeystoreProvider=$ksp_path;CEKeystoreName=$ksp_name;CEKeystoreEncryptKey=$encrypt_key;"; - } - if ( $keywords ) - { - $dsn .= $keywords; - } - $conn = new PDO( $dsn, $uid, $pwd, $options ); - $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); - return $conn; - } - catch( PDOException $e ) - { - var_dump( $e ); - exit; - } - catch(Exception $e) - { - var_dump( $e ); - exit; - } -} - - -/** - * @return string CEK name depending on the connection keywords - */ -function getCekName() -{ - require 'MsSetup.inc'; - $cekName = ''; - switch ( $keystore ) { - case "none": - $cekName = ''; - break; - case "win": - $cekName = 'AEColumnKey'; - break; - case "ksp": - $cekName = 'CustomCEK'; - break; - case "akv": - $cekName = 'AKVColumnKey'; - break; - default: - echo "getCekName: Invalid keystore name.\n"; - } - return $cekName; -} - - -/** - * class for encapsulating column metadata needed for creating a table - */ -class columnMeta { - public $colName; - public $dataType; //a string that includes the size of the type if necessary (e.g., decimal(10,5)) - public $encType; //randomized or deterministic; default is deterministic - public $options; //a string that is null by default (e.g. NOT NULL Identity (1,1) ) - - function __construct( $dataType, $colName = null, $options = null, $encType = "deterministic" ) - { - if ( is_null( $colName )) - { - $this->colName = get_default_colname( $dataType ); - } - else - { - $this->colName = $colName; - } - $this->dataType = $dataType; - $this->encType = $encType; - $this->options = $options; - } - /** - * @return string column definition for creating a table - */ - function getColDef() - { - require 'MsSetup.inc'; - $append = " "; - - // an identity column is not encrypted because a select query with identity column as the where clause is often run and the user want to have to bind parameter every time - if ( $keystore != "none" && stripos( $this->options, "identity" ) === false ) - { - $cekName = getCekName(); - if ( stripos( $this->dataType, "char" ) !== false ) - $append .= "COLLATE Latin1_General_BIN2 "; - $append .= sprintf( "ENCRYPTED WITH (ENCRYPTION_TYPE = %s, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = $cekName) ", $this->encType ); - } - $append .= $this->options; - $colDef = "[" . $this->colName . "] " . $this->dataType . $append; - return $colDef; - } -} - - -/** - * @return string default column name when a name is not provided in the columnMeta class - */ -function get_default_colname( $dataType ) -{ - $colName = "c_" . str_replace( ",", "_", str_replace( "(", "_", $dataType )); - $colName = rtrim( $colName, ")" ); - return $colName; -} - - /** * Create a table * @param object $conn : PDO connection object diff --git a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc index dd183c32..7aa915a0 100644 --- a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc +++ b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc @@ -13,10 +13,6 @@ // to be runnable from the MSSQL teams' internal proprietary test running system // -const KSP_NAME = 'MyCustomKSPName'; -const ENCRYPT_KEY = 'LPKCWVD07N3RG98J0MBLG4H2'; -const KSP_TEST_TABLE = 'CustomKSPTestTable'; - function isAEQualified($conn) { $msodbcsql_ver = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)["DriverVer"]; @@ -52,7 +48,7 @@ function connect($keywords = '', $options=array(), $errmode = PDO::ERRMODE_EXCEP // simply use $databaseName from MsSetup.inc to facilitate testing in Azure, // which does not support switching databases require("MsSetup.inc"); - $dsn = getDSN($server, $databaseName, $keywords, $disableCE); + $dsn = getDSN($server, $databaseName, $driver, $keywords, $disableCE); $conn = new PDO($dsn, $uid, $pwd, $options); if ($errmode == PDO::ERRMODE_EXCEPTION || $errmode == PDO::ERRMODE_WARNING || $errmode == PDO::ERRMODE_SILENT) { $conn->setAttribute(PDO::ATTR_ERRMODE, $errmode); @@ -76,7 +72,7 @@ function connect($keywords = '', $options=array(), $errmode = PDO::ERRMODE_EXCEP * @param bool $disableCE : flag for disabling column encryption even when keystore is NOT none * @return string dsn string used for PDO constructor */ -function getDSN($sqlsrvserver, $database, $keywords = '', $disableCE = false) +function getDSN($sqlsrvserver, $database, $driver, $keywords = '', $disableCE = false) { require("MsSetup.inc"); $dsn = ""; @@ -89,6 +85,9 @@ function getDSN($sqlsrvserver, $database, $keywords = '', $disableCE = false) if ($database) { $dsn .= "database=$database;"; } + if ($driver) { + $dsn .= "driver=$driver;"; + } if ($keystore != "none" && !$disableCE) { $dsn .= "ColumnEncryption=Enabled;"; } diff --git a/test/functional/pdo_sqlsrv/MsSetup.inc b/test/functional/pdo_sqlsrv/MsSetup.inc index e07c46a7..823f283c 100644 --- a/test/functional/pdo_sqlsrv/MsSetup.inc +++ b/test/functional/pdo_sqlsrv/MsSetup.inc @@ -18,7 +18,6 @@ if (isset($_ENV['MSSQL_SERVER']) || isset($_ENV['MSSQL_USER']) || isset($_ENV['M $uid = 'TARGET_USERNAME'; $pwd = 'TARGET_PASSWORD'; $databaseName = 'TARGET_DATABASE'; - $DriverName = "ODBC Driver 11 for SQL Server"; } $adServer = 'TARGET_AD_SERVER'; @@ -27,13 +26,12 @@ $adUser = 'TARGET_AD_USERNAME'; $adPassword = 'TARGET_AD_PASSWORD'; $driverType = true; -$PhpDriver = "ODBC Driver 11 for SQL Server"; +$driver = "ODBC Driver 17 for SQL Server"; $tableName = 'pdo_test_table'; $tableIndex = 'php_test_table_idx'; $procName = 'php_test_proc'; $fileName = 'php_test_file.dat'; -$dsn = "odbc:Driver={$DriverName};Server=$server"; $connectionOptions = array(); $daasMode = false; $marsMode = true; diff --git a/test/functional/pdo_sqlsrv/PDO21_Connection.phpt b/test/functional/pdo_sqlsrv/PDO21_Connection.phpt index f0989962..9498a358 100644 --- a/test/functional/pdo_sqlsrv/PDO21_Connection.phpt +++ b/test/functional/pdo_sqlsrv/PDO21_Connection.phpt @@ -15,7 +15,7 @@ try { // Invalid connection attempt => errors are expected $serverName="InvalidServerName"; - $dsn = getDSN($serverName, $databaseName); + $dsn = getDSN($serverName, $databaseName, $driver); $conn1 = new PDO($dsn, $uid, $pwd, $connectionOptions); if ($conn1) { printf("Invalid connection attempt should have failed.\n"); diff --git a/test/functional/pdo_sqlsrv/pdo_020_bind_params_array.phpt b/test/functional/pdo_sqlsrv/pdo_020_bind_params_array.phpt index 577ec0c5..ce12443d 100644 --- a/test/functional/pdo_sqlsrv/pdo_020_bind_params_array.phpt +++ b/test/functional/pdo_sqlsrv/pdo_020_bind_params_array.phpt @@ -12,6 +12,8 @@ try { // Create table $tableName = 'bindParams'; + dropTable($conn, $tableName); + $sql = "CREATE TABLE $tableName (ID TINYINT, SID CHAR(5))"; $stmt = $conn->exec($sql); diff --git a/test/functional/pdo_sqlsrv/pdo_040_error_information.phpt b/test/functional/pdo_sqlsrv/pdo_040_error_information.phpt index 93b6e2fd..c8424856 100644 --- a/test/functional/pdo_sqlsrv/pdo_040_error_information.phpt +++ b/test/functional/pdo_sqlsrv/pdo_040_error_information.phpt @@ -12,6 +12,8 @@ try { // Create table $tableName = 'pdo_040test'; + dropTable($conn, $tableName); + // common function insertRow() is not used here since the test deliberately // executes an invalid insertion statement // thus it's not necessary to create an encrypted column for testing column encryption diff --git a/test/functional/pdo_sqlsrv/pdo_065_construct_persistent.phpt b/test/functional/pdo_sqlsrv/pdo_065_construct_persistent.phpt index 883da029..8f2d8e8f 100644 --- a/test/functional/pdo_sqlsrv/pdo_065_construct_persistent.phpt +++ b/test/functional/pdo_sqlsrv/pdo_065_construct_persistent.phpt @@ -13,7 +13,7 @@ require_once("MsCommon_mid-refactor.inc"); try { echo "Testing a connection with ATTR_PERSISTENT...\n"; // setting PDO::ATTR_PERSISTENT in PDO constructor returns an exception - $dsn = getDSN($server, $databaseName); + $dsn = getDSN($server, $databaseName, $driver); $attr = array(PDO::ATTR_PERSISTENT => true); $conn = new PDO($dsn, $uid, $pwd, $attr); //free the connection diff --git a/test/functional/pdo_sqlsrv/pdo_065_construct_prefetch.phpt b/test/functional/pdo_sqlsrv/pdo_065_construct_prefetch.phpt index 463b7ac4..88f47495 100644 --- a/test/functional/pdo_sqlsrv/pdo_065_construct_prefetch.phpt +++ b/test/functional/pdo_sqlsrv/pdo_065_construct_prefetch.phpt @@ -10,7 +10,7 @@ require_once("MsSetup.inc"); require_once("MsCommon_mid-refactor.inc"); try { echo "Testing a connection with ATTR_PREFETCH before ERRMODE_EXCEPTION...\n"; - $dsn = getDSN($server, $databaseName); + $dsn = getDSN($server, $databaseName, $driver); $attr = array(PDO::ATTR_PREFETCH => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); $conn = new PDO($dsn, $uid, $pwd, $attr); diff --git a/test/functional/pdo_sqlsrv/pdo_ae_output_param_all.phpt b/test/functional/pdo_sqlsrv/pdo_ae_output_param_all.phpt index 580bbdcf..ea20d7ec 100644 --- a/test/functional/pdo_sqlsrv/pdo_ae_output_param_all.phpt +++ b/test/functional/pdo_sqlsrv/pdo_ae_output_param_all.phpt @@ -29,6 +29,7 @@ $colMetaArr = array("c1_int" => "int", createTable($conn, $tbname, $colMetaArr); // Create a Store Procedure $spname = 'selectAllColumns'; +dropProc($conn, $spname); $spSql = "CREATE PROCEDURE $spname ( @c1_int int OUTPUT, @c2_smallint smallint OUTPUT, @c3_tinyint tinyint OUTPUT, @c4_bit bit OUTPUT, diff --git a/test/functional/pdo_sqlsrv/pdo_utf8_conn.phpt b/test/functional/pdo_sqlsrv/pdo_utf8_conn.phpt index f51d3ba6..a5c31e09 100644 --- a/test/functional/pdo_sqlsrv/pdo_utf8_conn.phpt +++ b/test/functional/pdo_sqlsrv/pdo_utf8_conn.phpt @@ -4,6 +4,7 @@ UTF-8 connection strings --FILE-- ---FILE-- -query($query); - $master_key_row = $stmt->fetch(); - - $query = "SELECT name FROM sys.column_encryption_keys"; - $stmt = $conn->query($query); - $encryption_key_row = $stmt->fetch(); - - if ($master_key_row[0] == 'AEMasterKey' && $encryption_key_row[0] == 'AEColumnKey'){ - echo "Test Successfully done.\n"; - } - else { - die("Column Master Key and Column Encryption Key not created.\n"); - } - unset($stmt); -} -else { - echo "Test Successfully done.\n"; -} -unset($conn); -?> ---EXPECT-- +--TEST-- +Test the existence of Windows Always Encrypted keys generated in the database setup +--DESCRIPTION-- +This test iterates through the rows of sys.column_master_keys and/or +sys.column_encryption_keys to look for the specific column master key and +column encryption key generated in the database setup +--SKIPIF-- + +--FILE-- +query($query); + + // Do not assume the master key must be the first one created + $found = false; + while ($master_key_row = $stmt->fetch()) { + if ($master_key_row[0] == 'AEMasterKey') { + $found = true; + } + } + if (!$found) { + die("Windows Column Master Key not created.\n"); + } + + // Do not assume the encryption key must be the first one created + $query = "SELECT name FROM sys.column_encryption_keys"; + $stmt = $conn->query($query); + + $found = false; + while ($encryption_key_row = $stmt->fetch()) { + if ($encryption_key_row[0] == 'AEColumnKey') { + $found = true; + } + } + if (!$found) { + die("Windows Column Encryption Key not created.\n"); + } + unset($stmt); +} + +echo "Test Successfully done.\n"; +unset($conn); +?> +--EXPECT-- Test Successfully done. \ No newline at end of file diff --git a/test/functional/sqlsrv/MsSetup.inc b/test/functional/sqlsrv/MsSetup.inc index 1ec7ceef..aec2b4bb 100644 --- a/test/functional/sqlsrv/MsSetup.inc +++ b/test/functional/sqlsrv/MsSetup.inc @@ -18,7 +18,9 @@ $tableIndex = "php_test_table_index"; $procName = "php_test_proc"; $fileName = "php_test_file.dat"; -$connectionOptions = array("Database"=>$database, "UID"=>$userName, "PWD"=>$userPassword, "TraceOn"=>false); +$driver = "ODBC Driver 17 for SQL Server"; + +$connectionOptions = array("Database" => $database, "UID" => $userName, "PWD" => $userPassword, "TraceOn" => false, "Driver" => $driver); $daasMode = false; $marsMode = true; diff --git a/test/functional/sqlsrv/skipif_not_akv.inc b/test/functional/sqlsrv/skipif_not_akv.inc index f56a4522..9746db71 100644 --- a/test/functional/sqlsrv/skipif_not_akv.inc +++ b/test/functional/sqlsrv/skipif_not_akv.inc @@ -4,6 +4,12 @@ if (! extension_loaded("sqlsrv")) { die("skip extension not loaded"); } +require_once("MsSetup.inc"); +if ($driver != "ODBC Driver 17 for SQL Server") { + // the testing is not set to use ODBC 17 + die("skip - AE feature not supported in the current environment."); +} + require_once('MsCommon.inc'); $conn = AE\connect(); diff --git a/test/functional/sqlsrv/test_ae_keys_setup.phpt b/test/functional/sqlsrv/test_ae_keys_setup.phpt index e70257a2..53a2c0fa 100644 --- a/test/functional/sqlsrv/test_ae_keys_setup.phpt +++ b/test/functional/sqlsrv/test_ae_keys_setup.phpt @@ -1,5 +1,9 @@ --TEST-- -retrieval of names of column master key and column encryption key generated in the database setup +Test the existence of Windows Always Encrypted keys generated in the database setup +--DESCRIPTION-- +This test iterates through the rows of sys.column_master_keys and/or +sys.column_encryption_keys to look for the specific column master key and +column encryption key generated in the database setup --SKIPIF-- --FILE-- @@ -13,23 +17,34 @@ $conn = connect(); if (AE\IsQualified($conn)) { $query = "SELECT name FROM sys.column_master_keys"; $stmt = sqlsrv_query($conn, $query); - sqlsrv_fetch($stmt); - $master_key_name = sqlsrv_get_field($stmt, 0); + $found = false; + while (sqlsrv_fetch($stmt)) { + $master_key_name = sqlsrv_get_field($stmt, 0); + if ($master_key_name == 'AEMasterKey') { + $found = true; + } + } + // $master_key_name = sqlsrv_get_field($stmt, 0); + if (!$found) { + die("Windows Column Master Key not created.\n"); + } $query = "SELECT name FROM sys.column_encryption_keys"; $stmt = sqlsrv_query($conn, $query); - sqlsrv_fetch($stmt); - $encryption_key_name = sqlsrv_get_field($stmt, 0); - - if ($master_key_name == 'AEMasterKey' && $encryption_key_name == 'AEColumnKey') { - echo "Test Successfully done.\n"; - } else { - echo "Column Master Key and Column Encryption Key not created.\n"; + $found = false; + while (sqlsrv_fetch($stmt)) { + $encryption_key_name = sqlsrv_get_field($stmt, 0); + if ($encryption_key_name == 'AEColumnKey') { + $found = true; + } + } + if (!$found) { + die("Windows Column Encryption Key not created.\n"); } sqlsrv_free_stmt($stmt); -} else { - echo "Test Successfully done.\n"; } + +echo "Test Successfully done.\n"; sqlsrv_close($conn); ?> --EXPECT--