Monitoreo de secuencias de actividades de la base de datos - Amazon Relational Database Service

Monitoreo de secuencias de actividades de la base de datos

Los flujos de actividad de la base de datos monitorean y notifican las actividades. La secuencia de actividades se recopila y se transmite a Amazon Kinesis. Desde Kinesis, puede monitorear la secuencia de actividad, o bien otros servicios y aplicaciones pueden consumir la secuencia de actividades para un análisis posterior. Puede encontrar el nombre del flujo de Kinesis subyacente mediante el comando describe-db-instances de la AWS CLI o la operación de la API de RDS DescribeDBInstances.

Amazon RDS administra el flujo de Kinesis de la siguiente manera:

  • Amazon RDS crea el flujo de Kinesis automáticamente con un periodo de retención de 24 horas.

  • Amazon RDS escala el flujo de Kinesis si es necesario.

  • Si detiene el flujo de actividad de la base de datos o elimina la instancia de base de datos, Amazon RDS elimina el flujo de Kinesis.

Las categorías de actividad siguientes se monitorizan y se ponen en el registro de auditoría de secuencias de actividades:

  • Comandos SQL: todos los comandos SQL se auditan, así como las instrucciones preparadas, las funciones integradas y las funciones en lenguaje de procedimientos para SQL (PL/SQL). Las llamadas a procedimientos almacenados se auditan. Cualquier instrucción SQL emitida dentro de procedimientos o funciones almacenados también se auditan.

  • Otra información de la base de datos: la actividad monitoreada incluye la instrucción SQL completa, el recuento de las filas afectadas de los comandos DML, los objetos a los que se accede y el nombre único de la base de datos. Los flujos de actividad de la base de datos también monitorean las variables de enlace y los parámetros del procedimiento almacenados.

    importante

    El texto SQL completo de cada instrucción está visible en el registro de auditoría de secuencia de actividades, incluida la información confidencial. Sin embargo, las contraseñas de usuario de base de datos se redactan siOracle las puede determinar a partir del contexto, tal y como pasa con la siguiente instrucción SQL.

    ALTER ROLE role-name WITH password
  • Información de conexión: la actividad monitorizada incluye la información de sesión y de red, el ID de proceso del servidor y los códigos de salida.

Si un flujo de actividad tiene un error mientras monitorea una instancia de base de datos, se lo notificará mediante eventos RDS.

Acceso a una secuencia de actividades desde Kinesis

Cuando habilite un flujo de actividad para una base de datos, se creará un flujo de Kinesis para usted. En Kinesis podrá monitorizar la actividad de la base de datos en tiempo real. Para profundizar en el análisis de la actividad de la base de datos, puede conectar su secuencia de Kinesis a aplicaciones de consumidor. También puede conectar el flujo de datos con aplicaciones de administración de conformidad como Security Guardium de IBM o SecureSphere Database Audit and Protection de Imperva.

Puede acceder a su transmisión de Kinesis desde la consola de RDS o la consola de Kinesis.

Para acceder a una secuencia de actividades desde Kinesis utilizando la consola de RDS
  1. Abra la consola de Amazon RDS en https://console.aws.amazon.com/rds/.

  2. En el panel de navegación, elija Databases (Bases de datos).

  3. Elija la instancia de base de datos de Amazon RDS en la que desea iniciar un flujo de actividad.

  4. Elija Configuration (Configuración).

  5. En Database activity stream (Secuencia de actividad de base de datos), seleccione el enlace en Kinesis stream (Secuencia de Kinesis).

  6. En la colsola de Kinesis, elija Monitoring (Supervisión) para empezar a observar la actividad de la base de datos.

Para acceder a una secuencia de actividades desde Kinesis utilizando la consola de Kinesis
  1. Abra la consola de Kinesis en https://console.aws.amazon.com/kinesis.

  2. Elija la secuencia de actividades en la lista de secuencias de Kinesis.

    El nombre de un flujo de actividad consta de un prefijo aws-rds-das-db- seguido del ID de recurso de la base datos. A continuación se muestra un ejemplo.

    aws-rds-das-db-NHVOV4PCLWHGF52NP

    Para utilizar la consola de Amazon RDS para encontrar el ID de recurso del la base de datos, elija su instancia de base de datos en la lista de bases de datos y, luego, elija la pestaña Configuration (Configuración).

    Para utilizar la AWS CLI para encontrar el nombre completo del flujo de Kinesis de un flujo de actividad, utilice una solicitud describe-db-instances de la CLI y anote el valor de ActivityStreamKinesisStreamName en la respuesta.

  3. Elija Monitoring (Monitorización) para empezar a observar la actividad de la base de datos.

Para obtener más información acerca del uso de Amazon Kinesis, consulte ¿Qué es Amazon Kinesis Data Streams?.

Auditoría de contenido de registros y ejemplos

Los eventos monitoreados se representan en el flujo de actividad de la base de datos como cadenas JSON. La estructura está formada por un objeto JSON que contiene un DatabaseActivityMonitoringRecord, el cual, a su vez, contiene una matriz databaseActivityEventList de eventos de actividad.

Ejemplos de un registro de auditoría de flujo de actividad de la base de datos

A continuación mostramos registros de auditoría JSON descifrados de muestra de registros de eventos de actividad.

ejemplo Registro de eventos de actividad de una instrucción CONNECT SQL

El siguiente registro de eventos de actividad muestra un inicio de sesión con el uso de una instrucción SQL CONNECT (command) por parte de un JDBC Thin Client (clientApplication) para su base de datos 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 } }

El siguiente registro de eventos de actividad muestra un error de inicio de sesión en la base de datos de 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" } } ] }
nota

Si un flujo de actividad de la base de datos no está habilitado, el último campo del documento JSON es "engineNativeAuditFields": { }.

ejemplo Registro de evento de actividad de una instrucción CREATE TABLE

En el siguiente ejemplo, se muestra un evento CREATE TABLE para su base de datos 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 } }

En el siguiente ejemplo, se muestra un evento CREATE TABLE de la base de datos 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" } } ] }
ejemplo Registro de evento de actividad de una instrucción SELECT de Aurora PostgreSQL

En el siguiente ejemplo, se muestra un evento SELECT para su base de datos 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 } }

En el siguiente ejemplo, se muestra un evento SELECT para su base de datos 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" } } ] }

Objeto JSON DatabaseActivityMonitoringRecords

Los registros de eventos de actividad de la base de datos se encuentran en un objeto JSON que contiene la siguiente información.

Campo JSON Tipo de datos Descripción

type

string

Tipo de registro JSON. El valor es DatabaseActivityMonitoringRecords.

version string La versión de los registros de monitoreo de actividad de la base de datos. La base de datos Oracle utiliza la versión 1.3 y SQL Server utiliza la versión 1.4. Estas versiones del motor introducen el objeto JSON engineNativeAuditFields.

databaseActivityEvents

cadena

Un objeto JSON que contiene los eventos de actividad.

key cadena Una clave de cifrado que se utiliza para descifrar el databaseActivityEventList.

Objeto JSON databaseActivityEvents

El objeto JSON databaseActivityEvents contiene la siguiente información.

Campos de nivel superior en el registro JSON

Cada evento del registro de auditoría se envuelve dentro de un registro en formato JSON. Este registro contiene los siguientes campos.

type

Este campo siempre tiene el valor DatabaseActivityMonitoringRecords.

version

Este campo representa la versión del protocolo o contrato de datos del flujo de actividad de la base de datos. Define los campos que están disponibles.

databaseActivityEvents

Una cadena cifrada que representa uno o más eventos de actividad. Se representa como una matriz de bytes base64. Al descifrar la cadena, el resultado es un registro en formato JSON con campos, tal y como se muestra en los ejemplos de esta sección.

key

Clave de datos cifrada utilizada para cifrar la cadena databaseActivityEvents. Esta es la misma AWS KMS key que proporcionó cuando inició la secuencia de actividades de la base de datos.

En el ejemplo siguiente se muestra el formato de este registro.

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

Siga estos pasos para descifrar el contenido del campo databaseActivityEvents:

  1. Descifrar el valor en el campo JSON key mediante la clave de KMS que proporcionó al iniciar la secuencia de actividades de la base de datos. Al hacerlo, se devuelve la clave de cifrado de datos en texto sin cifrar.

  2. Decodifique en base64 el valor en el campo JSON databaseActivityEvents para obtener el texto cifrado, en formato binario, de la carga útil de auditoría.

  3. Descifrar el texto cifrado binario con la clave de cifrado de datos que decodificó en el primer paso.

  4. Descomprimir la carga útil descifrada.

    • La carga cifrada está en el campo databaseActivityEvents.

    • El campo databaseActivityEventList contiene una matriz de registros de auditoría. Los campos type de la matriz pueden ser record o heartbeat.

Un registro de evento de actividad de registro de auditoría es un objeto JSON que contiene la información siguiente.

Campo JSON Tipo de datos Descripción

type

string

Tipo de registro JSON. El valor es DatabaseActivityMonitoringRecord.

instanceId string El identificador del recurso de instancia de base de datos. Corresponde al atributo de instancia de base de datos DbiResourceId.

databaseActivityEventList

string

Una matriz de registros de auditoría de actividad o mensajes de latido.

Matriz de JSON databaseActivityEventList

La carga de registro de auditoría es una matriz JSON databaseActivityEventList cifrada. En la tabla siguiente, se enumeran alfabéticamente los campos de cada evento de actividad de la matriz DatabaseActivityEventList descifrada de un registro de auditoría.

Cuando la auditoría unificada está activada en la base de datos de Oracle, los registros de auditoría se rellenan en este nuevo seguimiento de auditoría. La vista UNIFIED_AUDIT_TRAIL muestra los registros de auditoría en forma tabular; para ello, recupera los registros de auditoría del seguimiento de auditoría. Cuando inicia un flujo de actividad de la base de datos, una columna en UNIFIED_AUDIT_TRAIL corresponde a un campo en la matriz databaseActivityEventList.

importante

La estructura de los eventos está sujeta a cambio. Amazon RDS podría agregar nuevos campos a eventos de actividad en el futuro. En las aplicaciones que analizan los datos JSON, asegúrese de que el código puede ignorar o tomar las acciones adecuadas para nombres de campo desconocidos.

Campos databaseActivityEventList para Amazon RDS para Oracle
Campo Tipo de datos Fuente Descripción

class

string

AUDIT_TYPE columna en UNIFIED_AUDIT_TRAIL

Clase de evento de actividad. Esto se corresponde con la AUDIT_TYPE columna de la vista UNIFIED_AUDIT_TRAIL. Los valores válidos para Amazon RDS para Oracle son los siguientes:

  • Standard

  • FineGrainedAudit

  • XS

  • Database Vault

  • Label Security

  • RMAN_AUDIT

  • Datapump

  • Direct path API

Para obtener más información, consulte UNIFIED_AUDIT_TRAIL en la documentación de Oracle.

clientApplication

string

CLIENT_PROGRAM_NAME en UNIFIED_AUDIT_TRAIL

Aplicación que el cliente ha usado para establecer conexión según notificación del cliente. No es obligatorio que el cliente notifique esta información, por lo que el valor puede ser nulo. Un valor de muestra es JDBC Thin Client.

command

string

ACTION_NAME columna en UNIFIED_AUDIT_TRAIL

Nombre de la acción ejecutada por el usuario. Para comprender la acción completa, lea tanto el nombre del comando como el valor AUDIT_TYPE. Un valor de muestra es ALTER DATABASE.

commandText

string

SQL_TEXT columna en UNIFIED_AUDIT_TRAIL

La instrucción SQL asociada con el evento Un valor de muestra es ALTER DATABASE BEGIN BACKUP.

databaseName

string

NAME columna en V$DATABASE

El nombre de la base de datos.

dbid

número

DBID columna en UNIFIED_AUDIT_TRAIL

Identificador numérico para la base de datos Un valor de muestra es 1559204751.

dbProtocol

string

N/A

Protocolo de la base de datos. En esta versión beta, el valor es oracle.

dbUserName

string

DBUSERNAME columna en UNIFIED_AUDIT_TRAIL

Nombre del usuario de la base de datos cuyas acciones se auditaron Un valor de muestra es RDSADMIN.

endTime

string

N/A

Este campo no se utiliza para RDS para Oracle y siempre es nulo.

engineNativeAuditFields

objeto

UNIFIED_AUDIT_TRAIL

De forma predeterminada, este objeto está vacío. Cuando inicia el flujo de actividad con la opción --engine-native-audit-fields-included, este objeto incluye las siguientes columnas y sus valores:

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

Para obtener más información, consulte UNIFIED_AUDIT_TRAIL en la documentación de Oracle Database.

errorMessage

string

N/A

Este campo no se utiliza para RDS para Oracle y siempre es nulo.

exitCode

número

RETURN_CODE columna en UNIFIED_AUDIT_TRAIL

Código de error de Oracle Database generado por la acción Si la acción se realizó correctamente, el valor es 0.

logTime

string

EVENT_TIMESTAMP_UTC columna en UNIFIED_AUDIT_TRAIL

Marca de tiempo de la creación de la entrada de seguimiento de auditoría. Un valor de muestra es 2020-11-27 06:56:14.981404.

netProtocol

string

AUTHENTICATION_TYPE columna en UNIFIED_AUDIT_TRAIL

Protocolo de comunicación de red Un valor de muestra es TCP.

objectName

string

OBJECT_NAME columna en UNIFIED_AUDIT_TRAIL

El nombre del objeto afectado por la acción Un valor de muestra es employees.

objectType

string

OBJECT_SCHEMA columna en UNIFIED_AUDIT_TRAIL

El nombre del esquema del objeto afectado por la acción Un valor de muestra es hr.

paramList

Lista

SQL_BINDS columna en UNIFIED_AUDIT_TRAIL

La lista de variables de enlace, si las hay, asociadas con SQL_TEXT Un valor de muestra es parameter_1,parameter_2.

pid

número

OS_PROCESS columna en UNIFIED_AUDIT_TRAIL

Identificador de proceso del sistema operativo del proceso de base de datos de Oracle Un valor de muestra es 22396.

remoteHost

string

AUTHENTICATION_TYPE columna en UNIFIED_AUDIT_TRAIL

La dirección IP del cliente o el nombre del anfitrión desde el que se generó la sesión Un valor de muestra es 123.456.789.123.

remotePort

string

AUTHENTICATION_TYPE columna en UNIFIED_AUDIT_TRAIL

Número de puerto del cliente. Un valor típico en entornos de Oracle Database es 1521.

rowCount

número

N/A

Este campo no se utiliza para RDS para Oracle y siempre es nulo.

serverHost

string

Anfitrión de base de datos

Dirección IP del anfitrión del servidor de base de datos. Un valor de muestra es 123.456.789.123.

serverType

string

N/A

Tipo de servidor de base de datos. Este valor siempre es ORACLE.

serverVersion

string

Anfitrión de base de datos

La versión de Amazon RDS para Oracle, la actualización de versión (RU) y la revisión de actualización de versión (RUR) Un valor de muestra es 19.0.0.0.ru-2020-01.rur-2020-01.r1.EE.3.

serviceName

string

Anfitrión de base de datos

Nombre del servicio de Un valor de muestra es oracle-ee.

sessionId

número

SESSIONID columna en UNIFIED_AUDIT_TRAIL

El identificador de sesión de la auditoría Un ejemplo es: 1894327130.

startTime

string

N/A

Este campo no se utiliza para RDS para Oracle y siempre es nulo.

statementId

número

STATEMENT_ID columna en UNIFIED_AUDIT_TRAIL

ID numérico para cada instrucción ejecutada Una instrucción puede causar muchas acciones. Un valor de muestra es 142197.

substatementId

N/A

N/A

Este campo no se utiliza para RDS para Oracle y siempre es nulo.

transactionId

string

TRANSACTION_ID columna en UNIFIED_AUDIT_TRAIL

El identificador de la transacción en la que se modifica el objeto Un valor de muestra es 02000800D5030000.

Campos databaseActivityEventList para Amazon RDS para SQL Server
Campo Tipo de datos Fuente Descripción

class

cadena

sys.fn_get_audit_file.class_type asignado a sys.dm_audit_class_type_map.class_type_desc

Clase de evento de actividad. Para obtener más información, consulte SQL Server Audit (Database Engine) (SQL Server Audit [motor de base de datos]) en la documentación de Microsoft SQL Server.

clientApplication

cadena

sys.fn_get_audit_file.application_name

La aplicación a la que se conecta el cliente según lo que informa el cliente (versión 14 y posteriores de SQL Server). Este campo es nulo en la versión 13 de SQL Server.

command

cadena

sys.fn_get_audit_file.action_id asignado a sys.dm_audit_actions.name

La categoría general de la instrucción SQL. El valor de este campo depende del valor de la clase.

commandText

cadena

sys.fn_get_audit_file.statement

Este campo indica la instrucción SQL.

databaseName

cadena

sys.fn_get_audit_file.database_name

Nombre de la base de datos.

dbProtocol

cadena

N/A

Protocolo de la base de datos. El valor es SQLSERVER.

dbUserName

cadena

sys.fn_get_audit_file.server_principal_name

El usuario de base de datos para la autenticación del cliente.

endTime

cadena

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

engineNativeAuditFields

objeto

Cada campo de sys.fn_get_audit_file que no aparece en esta columna.

De forma predeterminada, este objeto está vacío. Cuando inicia el flujo de actividad con la opción --engine-native-audit-fields-included, este objeto incluye otros campos de auditoría del motor nativo que este mapa JSON no devuelve.

errorMessage

cadena

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

exitCode

integer

sys.fn_get_audit_file.succeeded

Indica si la acción que inició el evento se realizó correctamente. Este campo no puede ser nulo. Para todos los eventos, excepto los eventos de inicio de sesión, este campo indica si la comprobación de permisos se realizó correctamente, pero no si la operación se realizó correctamente.

Entre los valores se encuentran:

  • 0: fallo

  • 1: correcto

logTime

cadena

sys.fn_get_audit_file.event_time

Marca de tiempo del evento que registra SQL Server.

netProtocol

cadena

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

objectName

cadena

sys.fn_get_audit_file.object_name

Nombre del objeto de base de datos si la instrucción SQL opera en un objeto.

objectType

cadena

sys.fn_get_audit_file.class_type asignado a sys.dm_audit_class_type_map.class_type_desc

Tipo de objeto de base de datos si la instrucción SQL opera en un tipo de objeto.

paramList

cadena

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

pid

integer

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

remoteHost

cadena

sys.fn_get_audit_file.client_ip

La dirección IP o el nombre de host del cliente que emitió la instrucción SQL (versión 14 y posteriores de SQL Server). Este campo es nulo en la versión 13 de SQL Server.

remotePort

integer

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

rowCount

integer

sys.fn_get_audit_file.affected_rows

El número de filas de la tabla afectadas por la instrucción SQL (versión 14 y posteriores de SQL Server). Este campo está en la versión 13 de SQL Server.

serverHost

cadena

Host de base de datos

Dirección IP del servidor de base de datos del host.

serverType

cadena

N/A

Tipo de servidor de base de datos. El valor es SQLSERVER.

serverVersion

cadena

Host de base de datos

La versión del servidor de base de datos, por ejemplo, 15.00.4073.23.v1.R1 para SQL Server 2017.

serviceName

cadena

Host de base de datos

Nombre del servicio de Un valor de ejemplo es sqlserver-ee.

sessionId

integer

sys.fn_get_audit_file.session_id

Identificador único de la sesión.

startTime

cadena

N/A

Amazon RDS para SQL Server no utiliza este campo y el valor es nulo.

statementId

cadena

sys.fn_get_audit_file.sequence_group_id

Identificador único de la instrucción SQL del cliente. El identificador es diferente para cada evento que se genera. Un valor de muestra es 0x38eaf4156267184094bb82071aaab644.

substatementId

integer

sys.fn_get_audit_file.sequence_number

Identificador para determinar el número de secuencia de una instrucción. Este identificador es útil cuando los registros grandes se dividen en varios registros.

transactionId

integer

sys.fn_get_audit_file.transaction_id

Identificador de una transacción. Si no hay ninguna transacción activa, el valor es cero.

type

cadena

Flujo de actividad de la base de datos generado

El tipo de evento. Los valores son record o heartbeat.

Procesamiento de un flujo de actividad de la base de datos mediante SDK de AWS

Puede procesar una secuencia de actividades mediante programación con AWS SDK. A continuación, mostramos ejemplos de Java y Python totalmente funcionales sobre cómo puede usar registros de flujos de actividad de la base de datos para la habilitación basada en instancias.

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()