Surveillance des flux d'activité de base de données - Amazon Relational Database Service

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Surveillance des flux d'activité de base de données

Les flux d'activité de base de données surveillent et rapportent les activités. Le flux d'activité est collecté et transmis à Amazon Kinesis. Depuis Kinesis, vous pouvez surveiller le flux d'activité ou d'autres services et applications peuvent utiliser le flux d'activité pour une analyse plus approfondie. Vous pouvez trouver le nom du flux Kinesis sous-jacent à l'aide de la AWS CLI commande ou de l'opération de l'API RDS.

Amazon RDS gère le flux Kinesis pour vous comme suit :

  • Amazon RDS crée automatiquement le flux Kinesis avec une période de rétention de 24 heures.

  • Amazon RDS met à l'échelle le flux Kinesis si nécessaire.

  • Si vous arrêtez le flux d'activité de base de données ou supprimez l'instance de base de données, Amazon RDS supprime le flux Kinesis.

Les catégories d'activité suivantes sont surveillées et incluses dans le journal d'audit de flux d'activité :

  • Commandes SQL – Toutes les commandes SQL sont auditées, ainsi que les instructions préparées, les fonctions intégrées et les fonctions en PL/SQL. Les appels aux procédures stockées sont vérifiés. Toutes les instructions SQL émises dans des procédures ou fonctions stockées sont également vérifiées.

  • Autres informations de bases de données – L'activité surveillée inclut l'instruction SQL complète, le nombre des lignes affectées par les commandes DML, les objets consultés et le nom unique de base de données. Les flux d'activité de base de données surveillent également les variables de liaison et les paramètres de procédure stockée.

    Important

    Le texte SQL complet de chaque instruction est visible dans le journal d'audit du flux d'activité, y compris les données sensibles. Cependant, les mots de passe des utilisateurs de base de données sont expurgés si Oracle peut les déterminer d'après le contexte, comme dans l'instruction SQL suivante.

    ALTER ROLE role-name WITH password
  • Informations de connexion – L'activité surveillée inclut les informations de session et de réseau, l'ID de processus serveur et les codes de sortie.

Si un flux d'activité rencontre un échec pendant la surveillance de votre instance de base de données, vous en êtes informé via des événements RDS.

Accès à un flux d'activité depuis Kinesis

Lorsque vous activez un flux d'activité pour une base de données, un flux Kinesis est créé pour vous. Depuis Kinesis, vous pouvez surveiller l'activité de votre base de données en temps réel. Pour effectuer des analyses plus poussées de l'activité de base de données, vous pouvez connecter votre flux Kinesis à des applications grand public. Vous pouvez également connecter le flux à des applications de gestion de la conformité telles que des SecureSphere bases de données d'Imperva.

Vous pouvez accéder à votre flux Kinesis à partir de la console RDS ou de la console Kinesis.

Pour accéder à un flux d'activité depuis Kinesis avec la console RDS
  1. Ouvrez la console Amazon RDS à l’adresse https://console.aws.amazon.com/rds/.

  2. Dans le panneau de navigation, choisissez Databases (Bases de données).

  3. Choisissez l'instance de base de données Amazon RDS où vous souhaitez démarrer un flux d'activité.

  4. Choisissez Configuration.

  5. Sous Database activity stream (Flux d'activité de la base de données), choisissez le lien sous Kinesis stream (Flux Kinesis).

  6. Dans la console Kinesis, choisissez Monitoring (Surveillance) pour commencer à observer l'activité de la base de données.

Pour accéder à un flux d'activité depuis Kinesis avec la console Kinesis
  1. Ouvrez la console Kinesis à l'adresse https://console.aws.amazon.com/kinesis.

  2. Choisissez votre flux d'activité dans la liste des flux Kinesis.

    Le nom d'un flux d'activité comprend le préfixe aws-rds-das-db- suivi de l'ID de ressource de la base de données. Voici un exemple de.

    aws-rds-das-db-NHVOV4PCLWHGF52NP

    Pour utiliser la console Amazon RDS afin de trouver l'ID de ressource pour la base de données, choisissez votre instance de base de données dans la liste des bases de données, puis choisissez l'onglet Configuration.

    AWS CLI Pour rechercher le nom complet du flux Kinesis d'un flux d'activité, utilisez une requête CLI et notez la valeur de ActivityStreamKinesisStreamName dans la réponse.

  3. Choisissez Surveillance pour commencer à observer l'activité de base de données.

Pour plus d'informations sur l'utilisation d'Amazon Kinesis, consultez la section En quoi consiste le service Amazon Kinesis Data Streams ?.

Contenus et exemples de journaux d'audit

Les événements surveillés sont représentés dans le flux d'activité de base de données sous la forme de chaînes JSON. La structure se compose d'un objet JSON contenant un DatabaseActivityMonitoringRecord, qui contient lui-même un tableau des événements d'activité databaseActivityEventList.

Exemples de journaux d'audit de flux d'activité

Vous trouverez ci-après des exemples de journaux d'audits JSON déchiffrés d'enregistrements d'événements d'activité.

Exemple Enregistrement d'événement d'activité d'une instruction CONNECT SQL

L'enregistrement d'événement d'activité suivant indique une connexion à l'aide d'une instruction SQL CONNECT (command) par un client léger JDBC (clientApplication) pour votre base de données Oracle.

{ "class": "Standard", "clientApplication": "JDBC Thin Client", "command": "LOGON", "commandText": null, "dbid": "0123456789", "databaseName": "ORCL", "dbProtocol": "oracle", "dbUserName": "TEST", "endTime": null, "errorMessage": null, "exitCode": 0, "logTime": "2021-01-15 00:15:36.233787", "netProtocol": "tcp", "objectName": null, "objectType": null, "paramList": [], "pid": 17904, "remoteHost": "123.456.789.012", "remotePort": "25440", "rowCount": null, "serverHost": "987.654.321.098", "serverType": "oracle", "serverVersion": "19.0.0.0.ru-2020-01.rur-2020-01.r1.EE.3", "serviceName": "oracle-ee", "sessionId": 987654321, "startTime": null, "statementId": 1, "substatementId": null, "transactionId": "0000000000000000", "engineNativeAuditFields": { "UNIFIED_AUDIT_POLICIES": "TEST_POL_EVERYTHING", "FGA_POLICY_NAME": null, "DV_OBJECT_STATUS": null, "SYSTEM_PRIVILEGE_USED": "CREATE SESSION", "OLS_LABEL_COMPONENT_TYPE": null, "XS_SESSIONID": null, "ADDITIONAL_INFO": null, "INSTANCE_ID": 1, "DBID": 123456789 "DV_COMMENT": null, "RMAN_SESSION_STAMP": null, "NEW_NAME": null, "DV_ACTION_NAME": null, "OLS_PROGRAM_UNIT_NAME": null, "OLS_STRING_LABEL": null, "RMAN_SESSION_RECID": null, "OBJECT_PRIVILEGES": null, "OLS_OLD_VALUE": null, "XS_TARGET_PRINCIPAL_NAME": null, "XS_NS_ATTRIBUTE": null, "XS_NS_NAME": null, "DBLINK_INFO": null, "AUTHENTICATION_TYPE": "(TYPE\u003d(DATABASE));(CLIENT ADDRESS\u003d((ADDRESS\u003d(PROTOCOL\u003dtcp)(HOST\u003d205.251.233.183)(PORT\u003d25440))));", "OBJECT_EDITION": null, "OLS_PRIVILEGES_GRANTED": null, "EXCLUDED_USER": null, "DV_ACTION_OBJECT_NAME": null, "OLS_LABEL_COMPONENT_NAME": null, "EXCLUDED_SCHEMA": null, "DP_TEXT_PARAMETERS1": null, "XS_USER_NAME": null, "XS_ENABLED_ROLE": null, "XS_NS_ATTRIBUTE_NEW_VAL": null, "DIRECT_PATH_NUM_COLUMNS_LOADED": null, "AUDIT_OPTION": null, "DV_EXTENDED_ACTION_CODE": null, "XS_PACKAGE_NAME": null, "OLS_NEW_VALUE": null, "DV_RETURN_CODE": null, "XS_CALLBACK_EVENT_TYPE": null, "USERHOST": "a1b2c3d4e5f6.amazon.com", "GLOBAL_USERID": null, "CLIENT_IDENTIFIER": null, "RMAN_OPERATION": null, "TERMINAL": "unknown", "OS_USERNAME": "sumepate", "OLS_MAX_READ_LABEL": null, "XS_PROXY_USER_NAME": null, "XS_DATASEC_POLICY_NAME": null, "DV_FACTOR_CONTEXT": null, "OLS_MAX_WRITE_LABEL": null, "OLS_PARENT_GROUP_NAME": null, "EXCLUDED_OBJECT": null, "DV_RULE_SET_NAME": null, "EXTERNAL_USERID": null, "EXECUTION_ID": null, "ROLE": null, "PROXY_SESSIONID": 0, "DP_BOOLEAN_PARAMETERS1": null, "OLS_POLICY_NAME": null, "OLS_GRANTEE": null, "OLS_MIN_WRITE_LABEL": null, "APPLICATION_CONTEXTS": null, "XS_SCHEMA_NAME": null, "DV_GRANTEE": null, "XS_COOKIE": null, "DBPROXY_USERNAME": null, "DV_ACTION_CODE": null, "OLS_PRIVILEGES_USED": null, "RMAN_DEVICE_TYPE": null, "XS_NS_ATTRIBUTE_OLD_VAL": null, "TARGET_USER": null, "XS_ENTITY_TYPE": null, "ENTRY_ID": 1, "XS_PROCEDURE_NAME": null, "XS_INACTIVITY_TIMEOUT": null, "RMAN_OBJECT_TYPE": null, "SYSTEM_PRIVILEGE": null, "NEW_SCHEMA": null, "SCN": 5124715 } }

L'enregistrement d'événement d'activité suivant indique un échec de connexion pour votre base de données SQL Server.

{ "type": "DatabaseActivityMonitoringRecord", "clusterId": "", "instanceId": "db-4JCWQLUZVFYP7DIWP6JVQ77O3Q", "databaseActivityEventList": [ { "class": "LOGIN", "clientApplication": "Microsoft SQL Server Management Studio", "command": "LOGIN FAILED", "commandText": "Login failed for user 'test'. Reason: Password did not match that for the login provided. [CLIENT: local-machine]", "databaseName": "", "dbProtocol": "SQLSERVER", "dbUserName": "test", "endTime": null, "errorMessage": null, "exitCode": 0, "logTime": "2022-10-06 21:34:42.7113072+00", "netProtocol": null, "objectName": "", "objectType": "LOGIN", "paramList": null, "pid": null, "remoteHost": "local machine", "remotePort": null, "rowCount": 0, "serverHost": "172.31.30.159", "serverType": "SQLSERVER", "serverVersion": "15.00.4073.23.v1.R1", "serviceName": "sqlserver-ee", "sessionId": 0, "startTime": null, "statementId": "0x1eb0d1808d34a94b9d3dcf5432750f02", "substatementId": 1, "transactionId": "0", "type": "record", "engineNativeAuditFields": { "target_database_principal_id": 0, "target_server_principal_id": 0, "target_database_principal_name": "", "server_principal_id": 0, "user_defined_information": "", "response_rows": 0, "database_principal_name": "", "target_server_principal_name": "", "schema_name": "", "is_column_permission": false, "object_id": 0, "server_instance_name": "EC2AMAZ-NFUJJNO", "target_server_principal_sid": null, "additional_information": "<action_info "xmlns=\"http://schemas.microsoft.com/sqlserver/2008/sqlaudit_data\"><pooled_connection>0</pooled_connection><error>0x00004818</error><state>8</state><address>local machine</address><PasswordFirstNibbleHash>B</PasswordFirstNibbleHash></action_info>"-->, "duration_milliseconds": 0, "permission_bitmask": "0x00000000000000000000000000000000", "data_sensitivity_information": "", "session_server_principal_name": "", "connection_id": "98B4F537-0F82-49E3-AB08-B9D33B5893EF", "audit_schema_version": 1, "database_principal_id": 0, "server_principal_sid": null, "user_defined_event_id": 0, "host_name": "EC2AMAZ-NFUJJNO" } } ] }
Note

Si un flux d'activité de base de données n'est pas activé, le dernier champ du document JSON est "engineNativeAuditFields": { }.

Exemple Registre d'événement d'activité d'une instruction CREATE TABLE

L'exemple suivant montre un événement CREATE TABLE pour votre base de données Oracle.

{ "class": "Standard", "clientApplication": "sqlplus@ip-12-34-5-678 (TNS V1-V3)", "command": "CREATE TABLE", "commandText": "CREATE TABLE persons(\n person_id NUMBER GENERATED BY DEFAULT AS IDENTITY,\n first_name VARCHAR2(50) NOT NULL,\n last_name VARCHAR2(50) NOT NULL,\n PRIMARY KEY(person_id)\n)", "dbid": "0123456789", "databaseName": "ORCL", "dbProtocol": "oracle", "dbUserName": "TEST", "endTime": null, "errorMessage": null, "exitCode": 0, "logTime": "2021-01-15 00:22:49.535239", "netProtocol": "beq", "objectName": "PERSONS", "objectType": "TEST", "paramList": [], "pid": 17687, "remoteHost": "123.456.789.0", "remotePort": null, "rowCount": null, "serverHost": "987.654.321.01", "serverType": "oracle", "serverVersion": "19.0.0.0.ru-2020-01.rur-2020-01.r1.EE.3", "serviceName": "oracle-ee", "sessionId": 1234567890, "startTime": null, "statementId": 43, "substatementId": null, "transactionId": "090011007F0D0000", "engineNativeAuditFields": { "UNIFIED_AUDIT_POLICIES": "TEST_POL_EVERYTHING", "FGA_POLICY_NAME": null, "DV_OBJECT_STATUS": null, "SYSTEM_PRIVILEGE_USED": "CREATE SEQUENCE, CREATE TABLE", "OLS_LABEL_COMPONENT_TYPE": null, "XS_SESSIONID": null, "ADDITIONAL_INFO": null, "INSTANCE_ID": 1, "DV_COMMENT": null, "RMAN_SESSION_STAMP": null, "NEW_NAME": null, "DV_ACTION_NAME": null, "OLS_PROGRAM_UNIT_NAME": null, "OLS_STRING_LABEL": null, "RMAN_SESSION_RECID": null, "OBJECT_PRIVILEGES": null, "OLS_OLD_VALUE": null, "XS_TARGET_PRINCIPAL_NAME": null, "XS_NS_ATTRIBUTE": null, "XS_NS_NAME": null, "DBLINK_INFO": null, "AUTHENTICATION_TYPE": "(TYPE\u003d(DATABASE));(CLIENT ADDRESS\u003d((PROTOCOL\u003dbeq)(HOST\u003d123.456.789.0)));", "OBJECT_EDITION": null, "OLS_PRIVILEGES_GRANTED": null, "EXCLUDED_USER": null, "DV_ACTION_OBJECT_NAME": null, "OLS_LABEL_COMPONENT_NAME": null, "EXCLUDED_SCHEMA": null, "DP_TEXT_PARAMETERS1": null, "XS_USER_NAME": null, "XS_ENABLED_ROLE": null, "XS_NS_ATTRIBUTE_NEW_VAL": null, "DIRECT_PATH_NUM_COLUMNS_LOADED": null, "AUDIT_OPTION": null, "DV_EXTENDED_ACTION_CODE": null, "XS_PACKAGE_NAME": null, "OLS_NEW_VALUE": null, "DV_RETURN_CODE": null, "XS_CALLBACK_EVENT_TYPE": null, "USERHOST": "ip-10-13-0-122", "GLOBAL_USERID": null, "CLIENT_IDENTIFIER": null, "RMAN_OPERATION": null, "TERMINAL": "pts/1", "OS_USERNAME": "rdsdb", "OLS_MAX_READ_LABEL": null, "XS_PROXY_USER_NAME": null, "XS_DATASEC_POLICY_NAME": null, "DV_FACTOR_CONTEXT": null, "OLS_MAX_WRITE_LABEL": null, "OLS_PARENT_GROUP_NAME": null, "EXCLUDED_OBJECT": null, "DV_RULE_SET_NAME": null, "EXTERNAL_USERID": null, "EXECUTION_ID": null, "ROLE": null, "PROXY_SESSIONID": 0, "DP_BOOLEAN_PARAMETERS1": null, "OLS_POLICY_NAME": null, "OLS_GRANTEE": null, "OLS_MIN_WRITE_LABEL": null, "APPLICATION_CONTEXTS": null, "XS_SCHEMA_NAME": null, "DV_GRANTEE": null, "XS_COOKIE": null, "DBPROXY_USERNAME": null, "DV_ACTION_CODE": null, "OLS_PRIVILEGES_USED": null, "RMAN_DEVICE_TYPE": null, "XS_NS_ATTRIBUTE_OLD_VAL": null, "TARGET_USER": null, "XS_ENTITY_TYPE": null, "ENTRY_ID": 12, "XS_PROCEDURE_NAME": null, "XS_INACTIVITY_TIMEOUT": null, "RMAN_OBJECT_TYPE": null, "SYSTEM_PRIVILEGE": null, "NEW_SCHEMA": null, "SCN": 5133083 } }

L'exemple suivant montre un événement CREATE TABLE pour votre base de données SQL Server.

{ "type": "DatabaseActivityMonitoringRecord", "clusterId": "", "instanceId": "db-4JCWQLUZVFYP7DIWP6JVQ77O3Q", "databaseActivityEventList": [ { "class": "SCHEMA", "clientApplication": "Microsoft SQL Server Management Studio - Query", "command": "ALTER", "commandText": "Create table [testDB].[dbo].[TestTable2](\r\ntextA varchar(6000),\r\n textB varchar(6000)\r\n)", "databaseName": "testDB", "dbProtocol": "SQLSERVER", "dbUserName": "test", "endTime": null, "errorMessage": null, "exitCode": 1, "logTime": "2022-10-06 21:44:38.4120677+00", "netProtocol": null, "objectName": "dbo", "objectType": "SCHEMA", "paramList": null, "pid": null, "remoteHost": "local machine", "remotePort": null, "rowCount": 0, "serverHost": "172.31.30.159", "serverType": "SQLSERVER", "serverVersion": "15.00.4073.23.v1.R1", "serviceName": "sqlserver-ee", "sessionId": 84, "startTime": null, "statementId": "0x5178d33d56e95e419558b9607158a5bd", "substatementId": 1, "transactionId": "4561864", "type": "record", "engineNativeAuditFields": { "target_database_principal_id": 0, "target_server_principal_id": 0, "target_database_principal_name": "", "server_principal_id": 2, "user_defined_information": "", "response_rows": 0, "database_principal_name": "dbo", "target_server_principal_name": "", "schema_name": "", "is_column_permission": false, "object_id": 1, "server_instance_name": "EC2AMAZ-NFUJJNO", "target_server_principal_sid": null, "additional_information": "", "duration_milliseconds": 0, "permission_bitmask": "0x00000000000000000000000000000000", "data_sensitivity_information": "", "session_server_principal_name": "test", "connection_id": "EE1FE3FD-EF2C-41FD-AF45-9051E0CD983A", "audit_schema_version": 1, "database_principal_id": 1, "server_principal_sid": "0x010500000000000515000000bdc2795e2d0717901ba6998cf4010000", "user_defined_event_id": 0, "host_name": "EC2AMAZ-NFUJJNO" } } ] }
Exemple Registre d'événement d'activité d'une instruction SELECT

L'exemple suivant montre un événement SELECT pour votre base de données Oracle.

{ "class": "Standard", "clientApplication": "sqlplus@ip-12-34-5-678 (TNS V1-V3)", "command": "SELECT", "commandText": "select count(*) from persons", "databaseName": "1234567890", "dbProtocol": "oracle", "dbUserName": "TEST", "endTime": null, "errorMessage": null, "exitCode": 0, "logTime": "2021-01-15 00:25:18.850375", "netProtocol": "beq", "objectName": "PERSONS", "objectType": "TEST", "paramList": [], "pid": 17687, "remoteHost": "123.456.789.0", "remotePort": null, "rowCount": null, "serverHost": "987.654.321.09", "serverType": "oracle", "serverVersion": "19.0.0.0.ru-2020-01.rur-2020-01.r1.EE.3", "serviceName": "oracle-ee", "sessionId": 1080639707, "startTime": null, "statementId": 44, "substatementId": null, "transactionId": null, "engineNativeAuditFields": { "UNIFIED_AUDIT_POLICIES": "TEST_POL_EVERYTHING", "FGA_POLICY_NAME": null, "DV_OBJECT_STATUS": null, "SYSTEM_PRIVILEGE_USED": null, "OLS_LABEL_COMPONENT_TYPE": null, "XS_SESSIONID": null, "ADDITIONAL_INFO": null, "INSTANCE_ID": 1, "DV_COMMENT": null, "RMAN_SESSION_STAMP": null, "NEW_NAME": null, "DV_ACTION_NAME": null, "OLS_PROGRAM_UNIT_NAME": null, "OLS_STRING_LABEL": null, "RMAN_SESSION_RECID": null, "OBJECT_PRIVILEGES": null, "OLS_OLD_VALUE": null, "XS_TARGET_PRINCIPAL_NAME": null, "XS_NS_ATTRIBUTE": null, "XS_NS_NAME": null, "DBLINK_INFO": null, "AUTHENTICATION_TYPE": "(TYPE\u003d(DATABASE));(CLIENT ADDRESS\u003d((PROTOCOL\u003dbeq)(HOST\u003d123.456.789.0)));", "OBJECT_EDITION": null, "OLS_PRIVILEGES_GRANTED": null, "EXCLUDED_USER": null, "DV_ACTION_OBJECT_NAME": null, "OLS_LABEL_COMPONENT_NAME": null, "EXCLUDED_SCHEMA": null, "DP_TEXT_PARAMETERS1": null, "XS_USER_NAME": null, "XS_ENABLED_ROLE": null, "XS_NS_ATTRIBUTE_NEW_VAL": null, "DIRECT_PATH_NUM_COLUMNS_LOADED": null, "AUDIT_OPTION": null, "DV_EXTENDED_ACTION_CODE": null, "XS_PACKAGE_NAME": null, "OLS_NEW_VALUE": null, "DV_RETURN_CODE": null, "XS_CALLBACK_EVENT_TYPE": null, "USERHOST": "ip-12-34-5-678", "GLOBAL_USERID": null, "CLIENT_IDENTIFIER": null, "RMAN_OPERATION": null, "TERMINAL": "pts/1", "OS_USERNAME": "rdsdb", "OLS_MAX_READ_LABEL": null, "XS_PROXY_USER_NAME": null, "XS_DATASEC_POLICY_NAME": null, "DV_FACTOR_CONTEXT": null, "OLS_MAX_WRITE_LABEL": null, "OLS_PARENT_GROUP_NAME": null, "EXCLUDED_OBJECT": null, "DV_RULE_SET_NAME": null, "EXTERNAL_USERID": null, "EXECUTION_ID": null, "ROLE": null, "PROXY_SESSIONID": 0, "DP_BOOLEAN_PARAMETERS1": null, "OLS_POLICY_NAME": null, "OLS_GRANTEE": null, "OLS_MIN_WRITE_LABEL": null, "APPLICATION_CONTEXTS": null, "XS_SCHEMA_NAME": null, "DV_GRANTEE": null, "XS_COOKIE": null, "DBPROXY_USERNAME": null, "DV_ACTION_CODE": null, "OLS_PRIVILEGES_USED": null, "RMAN_DEVICE_TYPE": null, "XS_NS_ATTRIBUTE_OLD_VAL": null, "TARGET_USER": null, "XS_ENTITY_TYPE": null, "ENTRY_ID": 13, "XS_PROCEDURE_NAME": null, "XS_INACTIVITY_TIMEOUT": null, "RMAN_OBJECT_TYPE": null, "SYSTEM_PRIVILEGE": null, "NEW_SCHEMA": null, "SCN": 5136972 } }

L'exemple suivant montre un événement SELECT pour votre base de données SQL Server.

{ "type": "DatabaseActivityMonitoringRecord", "clusterId": "", "instanceId": "db-4JCWQLUZVFYP7DIWP6JVQ77O3Q", "databaseActivityEventList": [ { "class": "TABLE", "clientApplication": "Microsoft SQL Server Management Studio - Query", "command": "SELECT", "commandText": "select * from [testDB].[dbo].[TestTable]", "databaseName": "testDB", "dbProtocol": "SQLSERVER", "dbUserName": "test", "endTime": null, "errorMessage": null, "exitCode": 1, "logTime": "2022-10-06 21:24:59.9422268+00", "netProtocol": null, "objectName": "TestTable", "objectType": "TABLE", "paramList": null, "pid": null, "remoteHost": "local machine", "remotePort": null, "rowCount": 0, "serverHost": "172.31.30.159", "serverType": "SQLSERVER", "serverVersion": "15.00.4073.23.v1.R1", "serviceName": "sqlserver-ee", "sessionId": 62, "startTime": null, "statementId": "0x03baed90412f564fad640ebe51f89b99", "substatementId": 1, "transactionId": "4532935", "type": "record", "engineNativeAuditFields": { "target_database_principal_id": 0, "target_server_principal_id": 0, "target_database_principal_name": "", "server_principal_id": 2, "user_defined_information": "", "response_rows": 0, "database_principal_name": "dbo", "target_server_principal_name": "", "schema_name": "dbo", "is_column_permission": true, "object_id": 581577110, "server_instance_name": "EC2AMAZ-NFUJJNO", "target_server_principal_sid": null, "additional_information": "", "duration_milliseconds": 0, "permission_bitmask": "0x00000000000000000000000000000001", "data_sensitivity_information": "", "session_server_principal_name": "test", "connection_id": "AD3A5084-FB83-45C1-8334-E923459A8109", "audit_schema_version": 1, "database_principal_id": 1, "server_principal_sid": "0x010500000000000515000000bdc2795e2d0717901ba6998cf4010000", "user_defined_event_id": 0, "host_name": "EC2AMAZ-NFUJJNO" } } ] }

DatabaseActivityMonitoringRecordsObjet JSON

Les enregistrements d'événement d'activité de base de données se trouvent dans un objet JSON qui contient les informations suivantes.

Champ JSON Type de données Description

type

chaîne

Type de l'enregistrement JSON. La valeur est DatabaseActivityMonitoringRecords.

version chaîne Version des enregistrements de surveillance d'activité de base de données. La base de données Oracle utilise la version 1.3 et SQL Server utilise la version 1.4. Ces versions du moteur introduisent l'objet JSON engineNativeAuditFields.

databaseActivityEvents

chaîne

Objet JSON qui contient les événements d'activité.

key chaîne Clé de chiffrement que vous utilisez pour déchiffrer databaseActivityEventListe

databaseActivityEvents Objet JSON

L'objet JSON databaseActivityEvents contient les informations suivantes.

Champs de niveau supérieur dans l'enregistrement JSON

Chaque événement du journal d'audit est encapsulé dans un enregistrement au format JSON. Cet enregistrement contient les champs suivants.

type

Ce champ a toujours la valeur DatabaseActivityMonitoringRecords.

version ;

Ce champ représente la version du contrat ou du protocole de données de flux d'activité de base de données. Il définit les champs disponibles.

databaseActivityEvents

Chaîne chiffrée représentant un ou plusieurs événements d'activité. Elle est représentée sou la forme d'un tableau base64 octets. Lorsque vous déchiffrez la chaîne, le résultat est un enregistrement au format JSON avec des champs comme ceux des exemples de cette section.

key

Clé de données chiffrée utilisée pour chiffrer la chaîne databaseActivityEvents. Il s'agit du même AWS KMS key que celui que vous avez fourni lorsque vous avez démarré le flux d'activité de la base de données.

L'exemple suivant illustre le format de cet enregistrement.

{ "type":"DatabaseActivityMonitoringRecords", "version":"1.3", "databaseActivityEvents":"encrypted audit records", "key":"encrypted key" }
"type":"DatabaseActivityMonitoringRecords", "version":"1.4", "databaseActivityEvents":"encrypted audit records", "key":"encrypted key"

Pour déchiffrer le contenu du champ databaseActivityEvents, procédez comme suit :

  1. Déchiffrez la valeur dans le champ JSON key à l'aide de la clé KMS que vous avez fournie lors du démarrage du flux d'activité de base de données. Cette opération renvoie la clé de chiffrement des données en texte clair.

  2. Décodez en base64 la valeur dans le champ JSON databaseActivityEvents pour obtenir le texte chiffré, au format binaire, de la charge utile d'audit.

  3. Déchiffrez le chiffrement binaire avec la clé de chiffrement de données que vous avez décodée au cours de la première étape.

  4. Décompressez la charge utile déchiffrée.

    • La charge utile chiffrée se trouve dans le champ databaseActivityEvents.

    • Le champ databaseActivityEventList contient un tableau d'enregistrements d'audits. Les champs type du tableau peuvent être record ou heartbeat.

L'enregistrement d'événement d'activité du journal d'audit est un objet JSON qui contient les informations suivantes.

Champ JSON Type de données Description

type

chaîne

Type de l'enregistrement JSON. La valeur est DatabaseActivityMonitoringRecord.

instanceId chaîne Identificateur de ressource d'instance de base de données. Il correspond à l'attribut d'instance de base de données DbiResourceId.

databaseActivityEventListe

chaîne

Tableau d'enregistrements d'audits d'activité ou de messages de pulsations.

databaseActivityEventTableau JSON de liste

La charge utile du journal d'audit est un tableau JSON databaseActivityEventList chiffré. Ci-dessous, le tableau répertorie par ordre alphabétique les champs de chaque événement d'activité dans le tableau DatabaseActivityEventList déchiffré d'un journal d'audit.

Lorsque l'audit unifié est activé dans Oracle Database, les enregistrements d'audit sont renseignés dans cette nouvelle trace d'audit. La vue UNIFIED_AUDIT_TRAIL affiche les enregistrements d'audit sous forme de tableau en extrayant les enregistrements d'audit de la trace d'audit. Lorsque vous démarrez un flux d'activité de base de données, une colonne dans UNIFIED_AUDIT_TRAIL mappe à un champ dans le tableau databaseActivityEventList.

Important

Il se peut que la structure d'événement change. Il se peut qu'Amazon RDS ajoute de nouveaux champs aux événements d'activité à l'avenir. Dans les applications qui analysent les données JSON, assurez-vous que votre code peut ignorer ou prendre les mesures appropriées pour les noms de champs inconnus.

databaseActivityEventChamps de liste pour Amazon RDS for Oracle
Champ Type de données Source Description

class

chaîne

Colonne AUDIT_TYPE dans UNIFIED_AUDIT_TRAIL

La classe d'un événement d'activité. Celle-ci correspond à la colonne AUDIT_TYPE dans la vue UNIFIED_AUDIT_TRAIL. Les valeurs valides pour Amazon RDS for Oracle sont les suivantes :

  • Standard

  • FineGrainedAudit

  • XS

  • Database Vault

  • Label Security

  • RMAN_AUDIT

  • Datapump

  • Direct path API

Pour plus d'informations, consultez UNIFIED_AUDIT_TRAIL dans la documentation Oracle.

clientApplication

chaîne

CLIENT_PROGRAM_NAME dans UNIFIED_AUDIT_TRAIL

Application utilisée par le client pour se connecter, telle que signalée par le client. Le client n'a pas à fournir cette information, la valeur peut être « null ». Un exemple de valeur est JDBC Thin Client.

command

chaîne

Colonne ACTION_NAME dans UNIFIED_AUDIT_TRAIL

Nom de l'action exécutée par l'utilisateur. Pour comprendre l'action complète, lisez le nom de la commande et la valeur AUDIT_TYPE. Un exemple de valeur est ALTER DATABASE.

commandText

chaîne

Colonne SQL_TEXT dans UNIFIED_AUDIT_TRAIL

Instruction SQL associée à l'événement. Un exemple de valeur est ALTER DATABASE BEGIN BACKUP.

databaseName

chaîne

Colonne NAME dans V$DATABASE

Nom de la base de données.

dbid

nombre

Colonne DBID dans UNIFIED_AUDIT_TRAIL

Identificateur numérique de la base de données. Un exemple de valeur est 1559204751.

dbProtocol

chaîne

N/A

Protocole de la base de données. Dans cette version bêta, la valeur est oracle.

dbUserName

chaîne

Colonne DBUSERNAME dans UNIFIED_AUDIT_TRAIL

Nom de l'utilisateur de la base de données dont les actions ont été auditées. Un exemple de valeur est RDSADMIN.

endTime

chaîne

N/A

Ce champ n'est pas utilisé pour RDS for Oracle. Sa valeur est toujours null.

engineNativeAuditFields

objet

UNIFIED_AUDIT_TRAIL

Par défaut, cet objet est vide. Lorsque vous démarrez le flux d'activité avec l'option --engine-native-audit-fields-included, cet objet inclut les colonnes et leurs valeurs suivantes :

ADDITIONAL_INFO APPLICATION_CONTEXTS AUDIT_OPTION AUTHENTICATION_TYPE CLIENT_IDENTIFIER CURRENT_USER DBLINK_INFO DBPROXY_USERNAME DIRECT_PATH_NUM_COLUMNS_LOADED DP_BOOLEAN_PARAMETERS1 DP_TEXT_PARAMETERS1 DV_ACTION_CODE DV_ACTION_NAME DV_ACTION_OBJECT_NAME DV_COMMENT DV_EXTENDED_ACTION_CODE DV_FACTOR_CONTEXT DV_GRANTEE DV_OBJECT_STATUS DV_RETURN_CODE DV_RULE_SET_NAME ENTRY_ID EXCLUDED_OBJECT EXCLUDED_SCHEMA EXCLUDED_USER EXECUTION_ID EXTERNAL_USERID FGA_POLICY_NAME GLOBAL_USERID INSTANCE_ID KSACL_SERVICE_NAME KSACL_SOURCE_LOCATION KSACL_USER_NAME NEW_NAME NEW_SCHEMA OBJECT_EDITION OBJECT_PRIVILEGES OLS_GRANTEE OLS_LABEL_COMPONENT_NAME OLS_LABEL_COMPONENT_TYPE OLS_MAX_READ_LABEL OLS_MAX_WRITE_LABEL OLS_MIN_WRITE_LABEL OLS_NEW_VALUE OLS_OLD_VALUE OLS_PARENT_GROUP_NAME OLS_POLICY_NAME OLS_PRIVILEGES_GRANTED OLS_PRIVILEGES_USED OLS_PROGRAM_UNIT_NAME OLS_STRING_LABEL OS_USERNAME PROTOCOL_ACTION_NAME PROTOCOL_MESSAGE PROTOCOL_RETURN_CODE PROTOCOL_SESSION_ID PROTOCOL_USERHOST PROXY_SESSIONID RLS_INFO RMAN_DEVICE_TYPE RMAN_OBJECT_TYPE RMAN_OPERATION RMAN_SESSION_RECID RMAN_SESSION_STAMP ROLE SCN SYSTEM_PRIVILEGE SYSTEM_PRIVILEGE_USED TARGET_USER TERMINAL UNIFIED_AUDIT_POLICIES USERHOST XS_CALLBACK_EVENT_TYPE XS_COOKIE XS_DATASEC_POLICY_NAME XS_ENABLED_ROLE XS_ENTITY_TYPE XS_INACTIVITY_TIMEOUT XS_NS_ATTRIBUTE XS_NS_ATTRIBUTE_NEW_VAL XS_NS_ATTRIBUTE_OLD_VAL XS_NS_NAME XS_PACKAGE_NAME XS_PROCEDURE_NAME XS_PROXY_USER_NAME XS_SCHEMA_NAME XS_SESSIONID XS_TARGET_PRINCIPAL_NAME XS_USER_NAME

Pour plus d'informations, consultez UNIFIED_AUDIT_TRAIL dans la documentation Oracle Database.

errorMessage

chaîne

N/A

Ce champ n'est pas utilisé pour RDS for Oracle. Sa valeur est toujours null.

exitCode

nombre

Colonne RETURN_CODE dans UNIFIED_AUDIT_TRAIL

Code d'erreur Oracle Database généré par l'action. Si l'action a réussi, la valeur est 0.

logTime

chaîne

Colonne EVENT_TIMESTAMP_UTC dans UNIFIED_AUDIT_TRAIL

Horodatage de la création de l'entrée de trace d'audit. Un exemple de valeur est 2020-11-27 06:56:14.981404.

netProtocol

chaîne

Colonne AUTHENTICATION_TYPE dans UNIFIED_AUDIT_TRAIL

Protocole de communication réseau. Un exemple de valeur est TCP.

objectName

chaîne

Colonne OBJECT_NAME dans UNIFIED_AUDIT_TRAIL

Nom de l'objet affecté par l'action. Un exemple de valeur est employees.

objectType

chaîne

Colonne OBJECT_SCHEMA dans UNIFIED_AUDIT_TRAIL

Nom de schéma de l'objet affecté par l'action. Un exemple de valeur est hr.

paramList

liste

Colonne SQL_BINDS dans UNIFIED_AUDIT_TRAIL

La liste des variables de liaison éventuelles associées à SQL_TEXT. Un exemple de valeur est parameter_1,parameter_2.

pid

nombre

Colonne OS_PROCESS dans UNIFIED_AUDIT_TRAIL

Identificateur de processus du système d'exploitation du processus de base de données Oracle. Un exemple de valeur est 22396.

remoteHost

chaîne

Colonne AUTHENTICATION_TYPE dans UNIFIED_AUDIT_TRAIL

Soit l'adresse IP du client, soit le nom de l'hôte à partir duquel la session a été générée. Un exemple de valeur est 123.456.789.123.

remotePort

chaîne

Colonne AUTHENTICATION_TYPE dans UNIFIED_AUDIT_TRAIL

Numéro de port du client. Une valeur typique dans les environnements Oracle Database est 1521.

rowCount

nombre

N/A

Ce champ n'est pas utilisé pour RDS for Oracle. Sa valeur est toujours null.

serverHost

chaîne

Hôte de base de données

Adresse IP de l'hôte du serveur de base de données. Un exemple de valeur est 123.456.789.123.

serverType

chaîne

N/A

Type de serveur de base de données. La valeur est toujours ORACLE.

serverVersion

chaîne

Hôte de base de données

Version d'Amazon RDS for Oracle, Release Update (RU) et Release Update Revision (RUR). Un exemple de valeur est 19.0.0.0.ru-2020-01.rur-2020-01.r1.EE.3.

serviceName

chaîne

Hôte de base de données

Nom du service. Un exemple de valeur est oracle-ee.

sessionId

nombre

Colonne SESSIONID dans UNIFIED_AUDIT_TRAIL

Identificateur de session de l'audit. Par exemple : 1894327130.

startTime

chaîne

N/A

Ce champ n'est pas utilisé pour RDS for Oracle. Sa valeur est toujours null.

statementId

nombre

Colonne STATEMENT_ID dans UNIFIED_AUDIT_TRAIL

ID numérique pour chaque exécution d'instruction. Une instruction peut provoquer de nombreuses actions. Un exemple de valeur est 142197.

substatementId

N/A

N/A

Ce champ n'est pas utilisé pour RDS for Oracle. Sa valeur est toujours null.

transactionId

chaîne

Colonne TRANSACTION_ID dans UNIFIED_AUDIT_TRAIL

L'identificateur de la transaction dans laquelle l'objet est modifié. Un exemple de valeur est 02000800D5030000.

databaseActivityEventChamps de liste pour Amazon RDS for SQL Server
Champ Type de données Source Description

class

chaîne

sys.fn_get_audit_file.class_type mappé sur sys.dm_audit_class_type_map.class_type_desc

La classe d'un événement d'activité. Pour plus d'informations, consultez Audit SQL Server (moteur de base de données) dans la documentation Microsoft.

clientApplication

chaîne

sys.fn_get_audit_file.application_name

Application à laquelle le client se connecte, comme indiqué par le client (SQL Server versions 14 et ultérieures). Ce champ a la valeur null dans SQL Server version 13.

command

chaîne

sys.fn_get_audit_file.action_id mappé sur sys.dm_audit_actions.name

Catégorie générale de l'instruction SQL. La valeur de ce champ dépend de la valeur de la classe.

commandText

chaîne

sys.fn_get_audit_file.statement

Ce champ indique l'instruction SQL.

databaseName

chaîne

sys.fn_get_audit_file.database_name

Nom du moteur de la base de données.

dbProtocol

chaîne

N/A

Protocole de la base de données. Cette valeur est SQLSERVER.

dbUserName

chaîne

sys.fn_get_audit_file.server_principal_name

L'utilisateur de la base de données pour l'authentification du client.

endTime

chaîne

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

engineNativeAuditFields

objet

Chaque champ dans sys.fn_get_audit_file qui n'est pas répertorié dans cette colonne.

Par défaut, cet objet est vide. Lorsque vous démarrez le flux d'activité avec l'option --engine-native-audit-fields-included, cet objet inclut d'autres champs d'audit de moteur natifs, qui ne sont pas renvoyés par cette carte JSON.

errorMessage

chaîne

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

exitCode

entier

sys.fn_get_audit_file.succeeded

Indique si l'action qui a démarré l'événement a réussi. Ce champ ne peut pas avoir la valeur null. Pour tous les événements, à l'exception des événements de connexion, ce champ indique si la vérification des autorisations a réussi ou échoué, mais pas si l'opération a réussi ou échoué.

Les valeurs sont les suivantes :

  • 0 – Échec

  • 1 – Réussite

logTime

chaîne

sys.fn_get_audit_file.event_time

Horodatage de l'événement enregistré par le serveur SQL Server.

netProtocol

chaîne

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

objectName

chaîne

sys.fn_get_audit_file.object_name

Nom de l'objet de base de données si l'instruction SQL agit sur un objet.

objectType

chaîne

sys.fn_get_audit_file.class_type mappé sur sys.dm_audit_class_type_map.class_type_desc

Type de l'objet de base de données si l'instruction SQL agit sur un type d'objet.

paramList

chaîne

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

pid

entier

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

remoteHost

chaîne

sys.fn_get_audit_file.client_ip

L'adresse IP ou le nom d'hôte du client qui a émis l'instruction SQL (SQL Server versions 14 et ultérieures). Ce champ a la valeur null dans SQL Server version 13.

remotePort

entier

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

rowCount

entier

sys.fn_get_audit_file.affected_rows

Nombre de lignes de la table affectées par l'instruction SQL (SQL Server versions 14 et ultérieures). Ce champ figure dans SQL Server version 13.

serverHost

chaîne

Hôte de base de données

Adresse IP du serveur de base de données hôte.

serverType

chaîne

N/A

Type de serveur de base de données. La valeur est SQLSERVER.

serverVersion

chaîne

Hôte de base de données

Version du serveur de base de données, par exemple 15.00.4073.23.v1.R1 pour SQL Server 2017.

serviceName

chaîne

Hôte de base de données

Nom du service. Un exemple de valeur est sqlserver-ee.

sessionId

entier

sys.fn_get_audit_file.session_id

Identificateur unique de la session.

startTime

chaîne

N/A

Ce champ n'est pas utilisé par Amazon RDS pour SQL Server et la valeur est null.

statementId

chaîne

sys.fn_get_audit_file.sequence_group_id

Identificateur unique de l'instruction SQL du client. L'identificateur est différent pour chaque événement généré. Un exemple de valeur est 0x38eaf4156267184094bb82071aaab644.

substatementId

entier

sys.fn_get_audit_file.sequence_number

Identificateur permettant de déterminer le numéro de séquence d'une instruction. Cet identificateur est utile quand des enregistrements volumineux sont divisés en plusieurs enregistrements.

transactionId

entier

sys.fn_get_audit_file.transaction_id

Identificateur d'une transaction. S'il n'existe pas de transactions actives, la valeur est zéro.

type

chaîne

Flux d'activité de base de données généré

Type d'événement. Les valeurs sont record ou heartbeat.

Traitement d'un flux d'activité de base de données à l'aide du AWS SDK

Vous pouvez traiter un flux d'activité par programmation à l'aide du AWS SDK. Les exemples suivants sont des exemples Java et Python entièrement fonctionnels d'utilisation des enregistrements de flux d'activité de base de données pour une activation basée sur des instances.

Java
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.InetAddress; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.zip.GZIPInputStream; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoInputStream; import com.amazonaws.encryptionsdk.jce.JceMasterKey; import com.amazonaws.services.kinesis.clientlibrary.exceptions.InvalidStateException; import com.amazonaws.services.kinesis.clientlibrary.exceptions.ShutdownException; import com.amazonaws.services.kinesis.clientlibrary.exceptions.ThrottlingException; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessor; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorCheckpointer; import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorFactory; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.InitialPositionInStream; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.KinesisClientLibConfiguration; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.ShutdownReason; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker; import com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker.Builder; import com.amazonaws.services.kinesis.model.Record; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.DecryptRequest; import com.amazonaws.services.kms.model.DecryptResult; import com.amazonaws.util.Base64; import com.amazonaws.util.IOUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class DemoConsumer { private static final String STREAM_NAME = "aws-rds-das-[instance-external-resource-id]"; // aws-rds-das-db-ABCD123456 private static final String APPLICATION_NAME = "AnyApplication"; //unique application name for dynamo table generation that holds kinesis shard tracking private static final String AWS_ACCESS_KEY = "[AWS_ACCESS_KEY_TO_ACCESS_KINESIS]"; private static final String AWS_SECRET_KEY = "[AWS_SECRET_KEY_TO_ACCESS_KINESIS]"; private static final String RESOURCE_ID = "[external-resource-id]"; // db-ABCD123456 private static final String REGION_NAME = "[region-name]"; //us-east-1, us-east-2... private static final BasicAWSCredentials CREDENTIALS = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY); private static final AWSStaticCredentialsProvider CREDENTIALS_PROVIDER = new AWSStaticCredentialsProvider(CREDENTIALS); private static final AwsCrypto CRYPTO = new AwsCrypto(); private static final AWSKMS KMS = AWSKMSClientBuilder.standard() .withRegion(REGION_NAME) .withCredentials(CREDENTIALS_PROVIDER).build(); class Activity { String type; String version; String databaseActivityEvents; String key; } class ActivityEvent { @SerializedName("class") String _class; String clientApplication; String command; String commandText; String databaseName; String dbProtocol; String dbUserName; String endTime; String errorMessage; String exitCode; String logTime; String netProtocol; String objectName; String objectType; List<String> paramList; String pid; String remoteHost; String remotePort; String rowCount; String serverHost; String serverType; String serverVersion; String serviceName; String sessionId; String startTime; String statementId; String substatementId; String transactionId; String type; } class ActivityRecords { String type; String clusterId; // note that clusterId will contain an empty string on RDS Oracle and RDS SQL Server String instanceId; List<ActivityEvent> databaseActivityEventList; } static class RecordProcessorFactory implements IRecordProcessorFactory { @Override public IRecordProcessor createProcessor() { return new RecordProcessor(); } } static class RecordProcessor implements IRecordProcessor { private static final long BACKOFF_TIME_IN_MILLIS = 3000L; private static final int PROCESSING_RETRIES_MAX = 10; private static final long CHECKPOINT_INTERVAL_MILLIS = 60000L; private static final Gson GSON = new GsonBuilder().serializeNulls().create(); private static final Cipher CIPHER; static { Security.insertProviderAt(new BouncyCastleProvider(), 1); try { CIPHER = Cipher.getInstance("AES/GCM/NoPadding", "BC"); } catch (NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) { throw new ExceptionInInitializerError(e); } } private long nextCheckpointTimeInMillis; @Override public void initialize(String shardId) { } @Override public void processRecords(final List<Record> records, final IRecordProcessorCheckpointer checkpointer) { for (final Record record : records) { processSingleBlob(record.getData()); } if (System.currentTimeMillis() > nextCheckpointTimeInMillis) { checkpoint(checkpointer); nextCheckpointTimeInMillis = System.currentTimeMillis() + CHECKPOINT_INTERVAL_MILLIS; } } @Override public void shutdown(IRecordProcessorCheckpointer checkpointer, ShutdownReason reason) { if (reason == ShutdownReason.TERMINATE) { checkpoint(checkpointer); } } private void processSingleBlob(final ByteBuffer bytes) { try { // JSON $Activity final Activity activity = GSON.fromJson(new String(bytes.array(), StandardCharsets.UTF_8), Activity.class); // Base64.Decode final byte[] decoded = Base64.decode(activity.databaseActivityEvents); final byte[] decodedDataKey = Base64.decode(activity.key); Map<String, String> context = new HashMap<>(); context.put("aws:rds:db-id", RESOURCE_ID); // Decrypt final DecryptRequest decryptRequest = new DecryptRequest() .withCiphertextBlob(ByteBuffer.wrap(decodedDataKey)).withEncryptionContext(context); final DecryptResult decryptResult = KMS.decrypt(decryptRequest); final byte[] decrypted = decrypt(decoded, getByteArray(decryptResult.getPlaintext())); // GZip Decompress final byte[] decompressed = decompress(decrypted); // JSON $ActivityRecords final ActivityRecords activityRecords = GSON.fromJson(new String(decompressed, StandardCharsets.UTF_8), ActivityRecords.class); // Iterate throught $ActivityEvents for (final ActivityEvent event : activityRecords.databaseActivityEventList) { System.out.println(GSON.toJson(event)); } } catch (Exception e) { // Handle error. e.printStackTrace(); } } private static byte[] decompress(final byte[] src) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(src); GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream); return IOUtils.toByteArray(gzipInputStream); } private void checkpoint(IRecordProcessorCheckpointer checkpointer) { for (int i = 0; i < PROCESSING_RETRIES_MAX; i++) { try { checkpointer.checkpoint(); break; } catch (ShutdownException se) { // Ignore checkpoint if the processor instance has been shutdown (fail over). System.out.println("Caught shutdown exception, skipping checkpoint." + se); break; } catch (ThrottlingException e) { // Backoff and re-attempt checkpoint upon transient failures if (i >= (PROCESSING_RETRIES_MAX - 1)) { System.out.println("Checkpoint failed after " + (i + 1) + "attempts." + e); break; } else { System.out.println("Transient issue when checkpointing - attempt " + (i + 1) + " of " + PROCESSING_RETRIES_MAX + e); } } catch (InvalidStateException e) { // This indicates an issue with the DynamoDB table (check for table, provisioned IOPS). System.out.println("Cannot save checkpoint to the DynamoDB table used by the Amazon Kinesis Client Library." + e); break; } try { Thread.sleep(BACKOFF_TIME_IN_MILLIS); } catch (InterruptedException e) { System.out.println("Interrupted sleep" + e); } } } } private static byte[] decrypt(final byte[] decoded, final byte[] decodedDataKey) throws IOException { // Create a JCE master key provider using the random key and an AES-GCM encryption algorithm final JceMasterKey masterKey = JceMasterKey.getInstance(new SecretKeySpec(decodedDataKey, "AES"), "BC", "DataKey", "AES/GCM/NoPadding"); try (final CryptoInputStream<JceMasterKey> decryptingStream = CRYPTO.createDecryptingStream(masterKey, new ByteArrayInputStream(decoded)); final ByteArrayOutputStream out = new ByteArrayOutputStream()) { IOUtils.copy(decryptingStream, out); return out.toByteArray(); } } public static void main(String[] args) throws Exception { final String workerId = InetAddress.getLocalHost().getCanonicalHostName() + ":" + UUID.randomUUID(); final KinesisClientLibConfiguration kinesisClientLibConfiguration = new KinesisClientLibConfiguration(APPLICATION_NAME, STREAM_NAME, CREDENTIALS_PROVIDER, workerId); kinesisClientLibConfiguration.withInitialPositionInStream(InitialPositionInStream.LATEST); kinesisClientLibConfiguration.withRegionName(REGION_NAME); final Worker worker = new Builder() .recordProcessorFactory(new RecordProcessorFactory()) .config(kinesisClientLibConfiguration) .build(); System.out.printf("Running %s to process stream %s as worker %s...\n", APPLICATION_NAME, STREAM_NAME, workerId); try { worker.run(); } catch (Throwable t) { System.err.println("Caught throwable while processing data."); t.printStackTrace(); System.exit(1); } System.exit(0); } private static byte[] getByteArray(final ByteBuffer b) { byte[] byteArray = new byte[b.remaining()]; b.get(byteArray); return byteArray; } }
Python
import base64 import json import zlib import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.internal.crypto import WrappingKey from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider from aws_encryption_sdk.identifiers import WrappingAlgorithm, EncryptionKeyType import boto3 REGION_NAME = '<region>' # us-east-1 RESOURCE_ID = '<external-resource-id>' # db-ABCD123456 STREAM_NAME = 'aws-rds-das-' + RESOURCE_ID # aws-rds-das-db-ABCD123456 enc_client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) class MyRawMasterKeyProvider(RawMasterKeyProvider): provider_id = "BC" def __new__(cls, *args, **kwargs): obj = super(RawMasterKeyProvider, cls).__new__(cls) return obj def __init__(self, plain_key): RawMasterKeyProvider.__init__(self) self.wrapping_key = WrappingKey(wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, wrapping_key=plain_key, wrapping_key_type=EncryptionKeyType.SYMMETRIC) def _get_raw_key(self, key_id): return self.wrapping_key def decrypt_payload(payload, data_key): my_key_provider = MyRawMasterKeyProvider(data_key) my_key_provider.add_master_key("DataKey") decrypted_plaintext, header = enc_client.decrypt( source=payload, materials_manager=aws_encryption_sdk.materials_managers.default.DefaultCryptoMaterialsManager(master_key_provider=my_key_provider)) return decrypted_plaintext def decrypt_decompress(payload, key): decrypted = decrypt_payload(payload, key) return zlib.decompress(decrypted, zlib.MAX_WBITS + 16) def main(): session = boto3.session.Session() kms = session.client('kms', region_name=REGION_NAME) kinesis = session.client('kinesis', region_name=REGION_NAME) response = kinesis.describe_stream(StreamName=STREAM_NAME) shard_iters = [] for shard in response['StreamDescription']['Shards']: shard_iter_response = kinesis.get_shard_iterator(StreamName=STREAM_NAME, ShardId=shard['ShardId'], ShardIteratorType='LATEST') shard_iters.append(shard_iter_response['ShardIterator']) while len(shard_iters) > 0: next_shard_iters = [] for shard_iter in shard_iters: response = kinesis.get_records(ShardIterator=shard_iter, Limit=10000) for record in response['Records']: record_data = record['Data'] record_data = json.loads(record_data) payload_decoded = base64.b64decode(record_data['databaseActivityEvents']) data_key_decoded = base64.b64decode(record_data['key']) data_key_decrypt_result = kms.decrypt(CiphertextBlob=data_key_decoded, EncryptionContext={'aws:rds:db-id': RESOURCE_ID}) print (decrypt_decompress(payload_decoded, data_key_decrypt_result['Plaintext'])) if 'NextShardIterator' in response: next_shard_iters.append(response['NextShardIterator']) shard_iters = next_shard_iters if __name__ == '__main__': main()