Klasifikasi Data
Gambaran Umum
Untuk mengelola data sensitif, SQL Server dan Azure SQL Server memperkenalkan kemampuan untuk menyediakan kolom database dengan metadata sensitivitas yang memungkinkan aplikasi klien menangani berbagai jenis data sensitif (seperti kesehatan, keuangan, dll.) sesuai dengan kebijakan perlindungan data.
Untuk informasi selengkapnya tentang cara menetapkan klasifikasi ke kolom, lihat Penemuan dan Klasifikasi Data SQL.
Microsoft ODBC Driver 17.2 atau yang lebih baru memungkinkan pengambilan metadata ini melalui SQLGetDescField menggunakan pengidentifikasi bidang SQL_CA_SS_DATA_CLASSIFICATION.
Format
SQLGetDescField memiliki sintaks berikut:
SQLRETURN SQLGetDescField(
SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber,
SQLSMALLINT FieldIdentifier,
SQLPOINTER ValuePtr,
SQLINTEGER BufferLength,
SQLINTEGER * StringLengthPtr);
DescriptorHandle
[Input] IRD (Deskriptor Baris Implementasi) menangani. Dapat diambil dengan panggilan ke SQLGetStmtAttr dengan atribut pernyataan SQL_ATTR_IMP_ROW_DESC
RecNumber
[Input] 0
FieldIdentifier
[Input] SQL_CA_SS_DATA_CLASSIFICATION
ValuePtr
[Output] Buffer output
BufferLength
[Input] Panjang buffer output dalam byte
StringLengthPtr [Output] Pointer ke buffer untuk mengembalikan jumlah total byte yang tersedia untuk dikembalikan dalam ValuePtr.
Catatan
Jika ukuran buffer tidak diketahui, itu dapat ditentukan dengan memanggil SQLGetDescField dengan ValuePtr sebagai NULL dan memeriksa nilai StringLengthPtr.
Jika informasi Klasifikasi Data tidak tersedia, kesalahan Bidang Deskriptor Tidak Valid akan dikembalikan.
Setelah panggilan berhasil ke SQLGetDescField, buffer yang ditunjukkan oleh ValuePtr akan berisi data berikut:
nn nn [n sensitivitylabels] tt tt [t informationtypes] cc cc [c columnsensitivitys]
Catatan
nn nn
, tt tt
, dan cc cc
adalah bilangan bulat multibyte, yang disimpan dengan byte paling tidak signifikan pada alamat terendah.
sensitivitylabel
dan informationtype
keduanya dari bentuk
nn [n bytes name] ii [i bytes id]
columnsensitivity
adalah dari bentuk
nn nn [n sensitivityprops]
Untuk setiap kolom (c), ada n 4-byte sensitivityprops
:
ss ss tt tt
s - indeks ke sensitivitylabels
dalam array, FF FF
jika tidak diberi label
t - indeks ke informationtypes
dalam array, FF FF
jika tidak diberi label
Format data dapat dinyatakan sebagai struktur pseudo berikut:
struct IDnamePair {
BYTE nameLen;
USHORT name[nameLen];
BYTE idLen;
USHORT id[idLen];
};
struct SensitivityProp {
USHORT labelIdx;
USHORT infoTypeIdx;
};
USHORT nLabels;
struct IDnamePair labels[nLabels];
USHORT nInfoTypes;
struct IDnamePair infotypes[nInfoTypes];
USHORT nColumns;
struct {
USHORT nProps;
struct SensitivityProp[nProps];
} columnClassification[nColumns];
Sampel kode
Aplikasi pengujian yang menunjukkan cara membaca metadata Klasifikasi Data. Pada Windows dapat dikompilasi menggunakan cl /MD dataclassification.c /I (directory of msodbcsql.h) /link odbc32.lib
dan dijalankan dengan string koneksi, dan kueri SQL (yang mengembalikan kolom rahasia) sebagai parameter:
#ifdef _WIN32
#include <windows.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <msodbcsql.h>
#include <stdio.h>
SQLHANDLE env, dbc, stmt;
void checkRC_exit(SQLRETURN rc, SQLHANDLE hand, SQLSMALLINT htype, int retcode, char *action)
{
if ((rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) && hand)
{
char msg[1024], state[6];
int i = 0;
SQLRETURN rc2;
SQLINTEGER err;
SQLSMALLINT lenout;
while ((rc2 = SQLGetDiagRec(htype, hand, ++i, state, &err, msg, sizeof(msg), &lenout)) == SQL_SUCCESS ||
rc2 == SQL_SUCCESS_WITH_INFO)
printf("%d (%d)[%s]%s\n", i, err, state, msg);
}
if (rc == SQL_ERROR && retcode)
{
printf("Error occurred%s%s\n", action ? " upon " : "", action ? action : "");
exit(retcode);
}
}
void printLabelInfo(char *type, char **pptr)
{
char *ptr = *pptr;
unsigned short nlabels;
printf("----- %s(%u) -----\n", type, nlabels = *(unsigned short*)ptr);
ptr += sizeof(unsigned short);
while (nlabels--)
{
int namelen, idlen;
char *nameptr, *idptr;
namelen = *ptr++;
nameptr = ptr;
ptr += namelen * 2;
idlen = *ptr++;
idptr = ptr;
ptr += idlen * 2;
wprintf(L"Name: \"%.*s\" Id: \"%.*s\"\n", namelen, nameptr, idlen, idptr);
}
*pptr = ptr;
}
int main(int argc, char **argv)
{
unsigned char *dcbuf;
unsigned int dclen = 0;
SQLRETURN rc;
SQLHANDLE ird;
if (argc < 3)
{
fprintf(stderr, "usage: dataclassification connstr query\n");
return 1;
}
checkRC_exit(SQLAllocHandle(SQL_HANDLE_ENV, 0, &env), 0, 0,
2, "allocate environment");
checkRC_exit(SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0), env, SQL_HANDLE_ENV,
3, "set ODBC version");
checkRC_exit(SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc), env, SQL_HANDLE_ENV,
4, "allocate connection");
checkRC_exit(SQLDriverConnect(dbc, 0, argv[1], SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT), dbc, SQL_HANDLE_DBC,
5, "connect to server");
checkRC_exit(SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt), dbc, SQL_HANDLE_DBC,
6, "allocate statement");
checkRC_exit(SQLExecDirect(stmt, argv[2], SQL_NTS), stmt, SQL_HANDLE_STMT,
7, "execute query");
checkRC_exit(SQLGetStmtAttr(stmt, SQL_ATTR_IMP_ROW_DESC, (SQLPOINTER)&ird, SQL_IS_POINTER, 0), stmt, SQL_HANDLE_STMT,
8, "get IRD handle");
rc = SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION, dcbuf, 0, &dclen);
checkRC_exit(rc, ird, SQL_HANDLE_DESC, 0, 0);
SQLINTEGER dclenout;
unsigned char *dcptr;
unsigned short ncols;
printf("Data Classification information (%u bytes):\n", dclen);
if (!(dcbuf = malloc(dclen)))
{
printf("Memory Allocation Error");
return 9;
}
checkRC_exit(SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION, dcbuf, dclen, &dclenout),
ird, SQL_HANDLE_DESC, 10, "reading SQL_CA_SS_DATA_CLASSIFICATION");
dcptr = dcbuf;
printLabelInfo("Labels", &dcptr);
printLabelInfo("Information Types", &dcptr);
printf("----- Column Sensitivities(%u) -----\n", ncols = *(unsigned short*)dcptr);
dcptr += sizeof(unsigned short);
while (ncols--)
{
unsigned short nprops = *(unsigned short*)dcptr;
dcptr += sizeof(unsigned short);
while (nprops--)
{
unsigned short labelidx, typeidx;
labelidx = *(unsigned short*)dcptr; dcptr += sizeof(unsigned short);
typeidx = *(unsigned short*)dcptr; dcptr += sizeof(unsigned short);
printf(labelidx == 0xFFFF ? "(none) " : "%u ", labelidx);
printf(typeidx == 0xFFFF ? "(none)\n" : "%u\n", typeidx);
}
printf("-----\n");
}
if (dcptr != dcbuf + dclen)
{
printf("Error: unexpected parse of DATACLASSIFICATION data\n");
return 11;
}
free(dcbuf);
return 0;
}
Versi yang Didukung
Microsoft ODBC Driver 17.2 memungkinkan pengambilan informasi Klasifikasi Data melalui SQLGetDescField
jika FieldIdentifier
diatur ke SQL_CA_SS_DATA_CLASSIFICATION
(1237).
Mulai dari Microsoft ODBC Driver 17.4.1.1, Anda dapat mengambil versi Klasifikasi Data yang didukung oleh server menggunakan SQLGetDescField
SQL_CA_SS_DATA_CLASSIFICATION_VERSION
pengidentifikasi bidang (1238). Dalam 17.4.1.1, versi klasifikasi data yang didukung diatur ke "2".
Mulai dari 17.4.2.1, versi default klasifikasi data diatur ke "1" dan merupakan versi yang dilaporkan driver ke SQL Server sebagai didukung. Atribut SQL_COPT_SS_DATACLASSIFICATION_VERSION
koneksi baru (1400) dapat memungkinkan aplikasi untuk mengubah versi Klasifikasi Data yang didukung dari "1" hingga maksimum yang didukung.
Contoh:
Untuk mengatur versi, panggilan ini harus dilakukan tepat sebelum panggilan SQLConnect atau SQLDriverConnect:
ret = SQLSetConnectAttr(dbc, SQL_COPT_SS_DATACLASSIFICATION_VERSION, (SQLPOINTER)2, SQL_IS_INTEGER);
Nilai versi Klasifikasi Data yang saat ini didukung dapat diambil melalui panggilan SQLGetConnectAttr:
ret = SQLGetConnectAttr(dbc, SQL_COPT_SS_DATACLASSIFICATION_VERSION, (SQLPOINTER)&dataClassVersion, SQL_IS_INTEGER, 0);