Klasifikasi Data

Unduh driver ODBC

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 SQLGetDescFieldSQL_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);