¿Cómo soluciono el error que recibo en CloudFormation cuando intento publicar registros lentos en registros de CloudWatch?
Quiero resolver el error que recibo en AWS CloudFormation cuando intento publicar registros lentos en Registros de Amazon CloudWatch. El error es: «La política de acceso a los recursos especificada para el grupo de registro de registros de CloudWatch /aws/aes/domains/search/search-logs no otorga permisos suficientes a Amazon Elasticsearch Service para crear una secuencia de registro».
Breve descripción
Para resolver este error, utilice una política independiente a nivel de grupo de registros para permitir que Amazon Elasticsearch Service (Amazon ES) envíe registros a Registros de CloudWatch. A continuación, utilice AccessPolicies en el recurso AWS::Elasticsearch::Domain para establecer los permisos de los dominios de Amazon ES.
Los siguientes pasos muestran cómo publicar registros lentos en CloudWatch con CloudFormation mediante un recurso personalizado respaldado por AWS Lambda creado en Python 3.6. El recurso personalizado activa una función de Lambda, que activa la API PutResourcePolicy para publicar registros lentos.
Nota: Cuando CloudFormation permite la publicación de registros en CloudWatch, el recurso AWS::Logs::LogGroup no tiene una propiedad para asignar una política de acceso a los recursos. La política de acceso a los recursos especificada para el grupo de registro de Registros de CloudWatch debe conceder permisos suficientes para que Amazon ES publique la secuencia de registro. No puede crear un permiso de política de acceso directamente mediante un recurso de CloudFormation. Esto se debe a que CloudFormation no admite la llamada a la API PutResourcePolicy para el recurso AWS::Logs::LogGroup.
Resolución
Nota: Si recibe errores al ejecutar los comandos de la Interfaz de la línea de comandos de AWS (AWS CLI), asegúrese de utilizar la versión más reciente de la AWS CLI.
La siguiente plantilla de CloudFormation utiliza un recurso personalizado para obtener el nombre del grupo de registro. A continuación, la plantilla aplica la política que permite al servicio de Amazon ES realizar llamadas a la API en el grupo de registro.
1. Cree una plantilla de CloudFormation llamada ESlogsPermission.yaml:
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AWSTemplateFormatVersion: 2010-09-09 Description: AWS cloudFormation template to publish slow logs to Amazon CloudWatch Logs. Parameters: LogGroupName: Type: String Description: Please don't change the log group name while updating ESDomainName: Description: A name for the Amazon Elastic Search domain Type: String LambdaFunctionName: Description: Lambda Function Name Type: String Resources: AwsLogGroup: Type: 'AWS::Logs::LogGroup' Properties: LogGroupName: !Ref LogGroupName LambdaLogGroup: Type: 'AWS::Logs::LogGroup' Properties: LogGroupName: !Sub '/aws/lambda/${LambdaFunctionName}' LambdaExecutionRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: root1 PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: !Sub >- arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:log-stream:* - PolicyName: root2 PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'logs:CreateLogGroup' Resource: - !Sub >- arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName} - !Sub >- arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/${LogGroupName} - Effect: Allow Action: - 'logs:PutResourcePolicy' - 'logs:DeleteResourcePolicy' Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*' logGroupPolicyFunction: DependsOn: LambdaLogGroup Type: 'AWS::Lambda::Function' Properties: FunctionName: !Ref LambdaFunctionName Code: ZipFile: > import urllib3 import json import boto3 http = urllib3.PoolManager() SUCCESS = "SUCCESS" FAILED = "FAILED" def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False): responseUrl = event['ResponseURL'] print(responseUrl) responseBody = {} responseBody['Status'] = responseStatus responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name responseBody['StackId'] = event['StackId'] responseBody['RequestId'] = event['RequestId'] responseBody['LogicalResourceId'] = event['LogicalResourceId'] responseBody['NoEcho'] = noEcho responseBody['Data'] = responseData json_responseBody = json.dumps(responseBody) print("Response body:\n" + json_responseBody) headers = { 'content-type' : '', 'content-length' : str(len(json_responseBody)) } try: response = http.request('PUT',responseUrl,body=json_responseBody.encode('utf-8'),headers=headers) print("Status code: " + response.reason) except Exception as e: print("send(..) failed executing requests.put(..): " + str(e)) def handler(event, context): logsgroup_policy_name=event['ResourceProperties']['CWLOGS_NAME'] cw_log_group_arn=event['ResourceProperties']['CWLOG_ARN'] cwlogs = boto3.client('logs') loggroup_policy={ "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "Service": "es.amazonaws.com"}, "Action":[ "logs:PutLogEvents", " logs:PutLogEventsBatch", "logs:CreateLogStream" ], 'Resource': f'{cw_log_group_arn}' }] } loggroup_policy = json.dumps(loggroup_policy) if(event['RequestType'] == 'Delete'): print("Request Type:",event['RequestType']) cwlogs.delete_resource_policy( policyName=logsgroup_policy_name ) responseData={} send(event, context, SUCCESS, responseData) elif(event['RequestType'] == 'Create'): try: cwlogs.put_resource_policy( policyName = logsgroup_policy_name, policyDocument = loggroup_policy ) responseData={} print("Sending response to custom resource") send(event, context, SUCCESS, responseData) except Exception as e: print('Failed to process:', e) send(event, context, FAILED, responseData) elif(event['RequestType'] == 'Update'): try: responseData={} print("Update is not supported on this resource") send(event, context, SUCCESS, responseData) except Exception as e: print('Failed to process:', e) send(event, context, FAILED, responseData) Handler: index.handler Role: !GetAtt - LambdaExecutionRole - Arn Runtime: python3.6 logGroupPolicycustomresource: Type: 'Custom::LogGroupPolicy' Properties: ServiceToken: !GetAtt - logGroupPolicyFunction - Arn CWLOGS_NAME: !Ref LogGroupName CWLOG_ARN: !GetAtt - AwsLogGroup - Arn ElasticsearchDomain: Type: 'AWS::Elasticsearch::Domain' DependsOn: logGroupPolicycustomresource Properties: DomainName: !Ref ESDomainName ElasticsearchVersion: '6.2' EBSOptions: EBSEnabled: true VolumeSize: 10 VolumeType: gp2 LogPublishingOptions: SEARCH_SLOW_LOGS: CloudWatchLogsLogGroupArn: !GetAtt - AwsLogGroup - Arn Enabled: true
2. Para lanzar una pila de CloudFormation con el archivoESlogsPermission.yaml, utilice la consola de CloudFormation o el siguiente comando de la AWS CLI:
aws cloudformation create-stack --stack-name yourStackName --template-body file://yourTemplateName --parameters ParameterKey=LogGroupName,ParameterValue=Your-LogGroup-Name, ParameterKey=ESDomainName,ParameterValue=Your-ES-Name --capabilities CAPABILITY_NAMED_IAM --region yourRegion
Nota: Sustituya yourStackName, yourTemplateName, Your-LogGroup-Name, Your-ES-Name, y yourRegion por sus valores.
La plantilla de CloudFormation hace lo siguiente por usted:
2. Crea una función de Lambda. La función de Lambda obtiene el nombre del grupo de registro de la sección Parámetros de la plantilla de CloudFormation mediante un recurso personalizado. La función de Lambda llama a la API PutResourcePolicy para obtener el nombre del grupo de registro. El grupo de registro debe tener una política que permita que el dominio de Amazon ES coloque los registros.
3. Crea un recurso personalizado respaldado por Lambda para invocar la función de Lambda creada en el paso 2. El recurso personalizado ayuda a aplicar PutResourcePolicy en el grupo de registro «nombre de recurso de Amazon (ARN)» para que Amazon ES pueda transmitir los registros. En la plantilla, CloudFormation utiliza un recurso personalizado para crear un dominio de Amazon ES con LogPublishingOption.
Contenido relevante
- OFICIAL DE AWSActualizada hace 3 años
- OFICIAL DE AWSActualizada hace 3 años
- OFICIAL DE AWSActualizada hace 3 años