web-dev-qa-db-fra.com

Autorisations d'accès à ElasticSearch depuis Lambda?

J'essaie d'utiliser Elasticsearch pour le stockage de données pour une fonction Lambda connectée à Alexa Skills Kit. La Lambda fonctionne bien sans Elasticsearch mais ES fournit une correspondance floue bien nécessaire.

La seule façon dont j'ai pu y accéder depuis Lambda est d'activer l'accès global à Elasticsearch, mais c'est une très mauvaise idée. J'ai également pu accéder à partir de mon ordinateur via une politique d'accès ouvert ou une politique d'adresse IP. Existe-t-il un moyen de faire un accès en lecture seule via Lambda et en lecture-écriture via IP?

Sur IAM, j'ai accordé mon rôle Lambda AmazonESReadOnlyAccess. Du côté ES, j'ai essayé cela, mais cela ne fonctionnait que pour l'adresse IP:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::NUMBER:root",
          "arn:aws:iam::NUMBER:role/lambda_basic_execution"
        ]
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-east-1:NUMBER:domain/NAME/*"
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-east-1:NUMBER:domain/NAME/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "MY IP"
        }
      }
    }
  ]
}

This forum post pose la même question mais est resté sans réponse.

17
Keith

La seule façon que je sache de le faire est d'utiliser une stratégie basée sur les ressources ou une stratégie basée sur IAM sur votre domaine ES. Cela restreindrait l'accès à un utilisateur ou un rôle IAM particulier. Cependant, pour que cela fonctionne, vous devez également signer vos demandes à ES à l'aide de SigV4.

Il y a des bibliothèques qui feront cette signature pour vous, par exemple celui-ci étend la populaire bibliothèque Python demandes pour signer les demandes ElasticSearch via SigV4. Je crois que des bibliothèques similaires existent pour autres langues.

9
garnaat

Maintenant, c'est possible à partir de votre code avec elasticsearch.js . Avant de l'essayer, vous devez installer le module http-aws-es .

const AWS = require('aws-sdk');
const httpAwsEs = require('http-aws-es');
const elasticsearch = require('elasticsearch');

const client = new elasticsearch.Client({
    Host: 'YOUR_ES_Host',
    connectionClass: httpAwsEs,
    amazonES: {
        region: 'YOUR_ES_REGION',
        credentials: new AWS.EnvironmentCredentials('AWS')
    }
});

// client.search({...})

Bien sûr, avant de l'utiliser, configurez l'accès au domaine elasticsearch: enter image description here

9
Iurii Golskyi
3
Shef

Pour un accès externe (en dehors d'AWS) à votre cluster Elasticsearch, vous souhaitez créer le cluster avec une stratégie d'accès basée sur IP. Quelque chose comme ci-dessous:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "<<IP/CIDR>>"
          ]
        }
      },
      "Resource": "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
    }
  ]
}

Pour votre fonction Lambda, créez le rôle que la fonction Lambda assumera avec l'extrait de stratégie ci-dessous.

{
  "Sid": "",
  "Effect": "Allow",
  "Action": [
    "es:DescribeElasticsearchDomain",
    "es:DescribeElasticsearchDomains",
    "es:DescribeElasticsearchDomainConfig",
    "es:ESHttpPost",
    "es:ESHttpPut"
  ],
  "Resource": [
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
  ]
},
{
  "Sid": "",
  "Effect": "Allow",
  "Action": [
    "es:ESHttpGet"
  ],
  "Resource": [
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_all/_settings",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_cluster/stats",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/<<INDEX>>*/_mapping/<<TYPE>>",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes/stats",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_nodes/*/stats",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/_stats",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/<<INDEX>>*/_stats"
  ]
}

Je pense que vous pourriez plus facilement condenser les deux déclarations de politique ci-dessus en ce qui suit:

{
  "Sid": "",
  "Effect": "Allow",
  "Action": [
    "es:DescribeElasticsearchDomain",
    "es:DescribeElasticsearchDomains",
    "es:DescribeElasticsearchDomainConfig",
    "es:ESHttpPost",
    "es:ESHttpGet",
    "es:ESHttpPut"
  ],
  "Resource": [
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>",
    "arn:aws:es:<<REGION>>:<<ACCOUNTID>>:domain/<<DOMAIN_NAME>>/*"
  ]
}

J'ai réussi à reconstituer ce qui précède à partir des sources suivantes:

https://aws.Amazon.com/blogs/security/how-to-control-access-to-your-Amazon-elasticsearch-service-domain/

Comment accéder à Kibana à partir du service Amazon elasticsearch?

https://forums.aws.Amazon.com/thread.jspa?threadID=217149

2
Brooks

AWS Lambda s'exécute sur des instances EC2 publiques. Donc, simplement ajouter une liste blanche d'adresses IP à la politique d'accès d'Elasticsearch ne fonctionnera pas. Une façon de procéder consiste à accorder au rôle d'exécution Lambda les autorisations appropriées sur le domaine Elasticsearch. Assurez-vous que le rôle Lambda Execution dispose d'autorisations sur le domaine ES et que la stratégie d'accès au domaine ES a une déclaration qui permet à cet ARN de rôle Lambda d'effectuer les actions appropriées. Une fois cela fait, il vous suffit de signer votre demande via SigV4 tout en accédant au point de terminaison ES

J'espère que cela pourra aider!

1
Raheel Kazi