49

I created Amazon elasticsearch service and populated data into it using logstash, which has been installed on an EC2 instance. On the Amazon elasticservice console page, there will be a link to access Kibana.

search-cluster_name-XXXXXXXXXXXXXXXXXXX.region_name.es.amazonaws.com/_plugin/kibana/

when I click the link, browser is throwing the following error.

{"Message":"User: anonymous is not authorized to perform: es:ESHttpGet on resource: arn:aws:es:region_name:account_id:domain/cluster_name/_plugin/kibana/"}

I'm sure that this has something related with access policy of ES domain.How should I modify my access policy so that I can access Kibana from a click on the link specified ?

AV94
  • 1,654
  • 2
  • 19
  • 32
  • 2
    If I change the access policy as you suggested,then anyone having knowledge of the url can access it right? – AV94 Nov 17 '15 at 07:53
  • In case you want to login to Kibana URL in your web-browser, either use the Master Password or use IAM role (but you have to use Cognito as well), otherwise it will show you a basic authentication login form in your browser that won't work. From doc: _If you choose to use IAM for user management, you must enable Amazon Cognito Authentication for Kibana and sign in using credentials from your user pool to access Kibana. Otherwise, Kibana shows a nonfunctional sign-in page._ – Edenshaw Mar 05 '20 at 14:31

5 Answers5

29

You can setup an Access Policy with both IAM and IP-address based access. See my answer here. In short:

  • EC2 instance needs a profile with the arn:aws:iam::aws:policy/AmazonESFullAccess policy
  • Policy should include two statements: first list IAM access, second list IP access.

Here's an example policy (statement order is important!)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*"
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "192.168.1.0",
            "192.168.1.1"
          ]
        }
      }
    }
  ]
}
Community
  • 1
  • 1
Pete
  • 9,450
  • 7
  • 50
  • 57
  • Thanks, seperating the Statment objects is where I went wrong. – cmrust Sep 28 '16 at 17:56
  • @pete so if my desktop IP is "192.168.1.66" then I should access kibana as http://192.168.1.66:9200/_plugin/kibana that doesn't work for me. – nad Jul 09 '17 at 18:54
  • You would set `{"aws:SourceIp": "192.168.1.66"}` and access Kibana via whatever URL is listed as the Kibana endpoint for a domain in [the management console](https://console.aws.amazon.com/es/home). Note if your local IP is /actually/ `192.168.1.66`, you might be connected to the Internet via a router and you'll need to enter the IP for your router. Also, only test after your domain status is `Active` (warning: could take 20 minutes every time you update the policy). – Pete Jul 10 '17 at 02:31
  • 3
    This seems like it's no longer working. It now results in: `UpdateElasticsearchDomainConfig: {"message":"You can’t attach an IP-based policy to a domain that has a VPC endpoint. Instead, use a security group to control IP-based access."}` – vascop Aug 07 '19 at 11:51
17

I used for that purpose proxy tool called aws-es-kibana. It signs all your requests sent to aws kibana.

IAM configuration:

I created new IAM user "elasticsearch_user" with programmatic access (and I got accessKeyId and secretAccessKey associated with that account).

Elasticsearch configuration:

I created elasticsearch policy that enables access for the new created IAM user:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::{YOUR_AWS_ACCOUNT_ID}:user/elasticsearch_user"
        ]
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:eu-central-1:{YOUR_AWS_ACCOUNT_ID}:domain/{YOUR_ELASTICSEARCH_DOMAIN}/*"
    }
  ]
}

Connect to kibana from your local station:

To connect from my local station (windows) to kibana I just need to type in console:

SET AWS_ACCESS_KEY_ID=myAccessKeyId
SET AWS_SECRET_ACCESS_KEY=mySecretAccessKey

aws-es-kibana search-{PROTECTED_PART_OF_YOUR_ELASTICSEARCH_ENDPOINT}.eu-central-1.es.amazonaws.com

After that you should have proxied access to your kibana under: http://127.0.0.1:9200/_plugin/kibana

luwojtaszek
  • 875
  • 1
  • 8
  • 8
5

You have to configure an access policy for your elasticsearch cluster. there are two options:

  1. Set up an IAM-based access policy
  2. White-list certain IPs from which people can access your Kibana instance.

Option 1, using IAM based access is the better option:

  • Create an IAM user, called kibana_user with programmatic access. Save the accessKeyId and the secretAccessKey. Also copy the user's ARN.
  • Configure your access policy to give access to kibana_user.
    • Go to https://eu-central-1.console.aws.amazon.com/es/
    • Select your elasticsearch domain
    • Click on "Modify access policty"
    • Click on "Select a template" and use the one that's called "Allow access to one or more AWS accounts or IAM users". Enter the ARN of the kibana_user Here is what it looks like
  • Unfortunately, AWS does not provide with a way to log in as that user and then connect to Kiabana. Instead, if wants you to sign the HTTP requests that you make to Kibana with that user's key. There are tools that do this for you, for example aws-es-proxy

I seriously recommend against the second option with IP-based access. Even if you have a static IP,

  • everybody on that IP will have access to your data on elasticesarch
  • you only have access if you are connected via that API. Not from your phone, not from home.

The only case where this makes sense is if you are running your own proxy server with its own authentication method and a static IP.

Konstantin Schubert
  • 2,661
  • 1
  • 26
  • 39
  • Is your IAM proxy code available anywhere? I’m Informa ken entering AWS keys into someone’s else site... – Konrads Mar 25 '18 at 11:48
  • The code is closed source (so far). But anyways the AWS credentials are stored in plain in my database, so you'll have to trust my anyways. I totally understand if you don't want to do that. YMMV... – Konstantin Schubert Mar 25 '18 at 19:08
4

In my case, I had an nginx server running which already had access to the elasticsearch service. So all I had to do was to add a proxy on this nginx. No changes in AWS IAM required.

Add this to /etc/nginx/sites-enabled/elasticsearch

server {
  listen   7777;
  server_name  127.0.0.1 default_server;
  access_log  /var/log/nginx/elasticsearch.access.log;
  location / {
    auth_basic "My Super Secret Server";
    auth_basic_user_file /etc/nginx/.elasticsearch_htpasswd;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_pass         https://<your_server_here>.es.amazonaws.com/;
        proxy_set_header Authorization "";
        proxy_hide_header Authorization;
  }
}

and restart nginx. Then you can access kibana at:

http://your_nginx_server_name.com:7777/_plugin/kibana/app/kibana#/dev_tools/console?_g=()

The file /etc/nginx/.elasticsearch_htpasswd is a standard apache2 htaccess file. You can find more about basic auth for nginx here.

NOTE: Basic auth is NOT a recommended way to secure anything. Definitely don't use this in production.

paneer_tikka
  • 5,403
  • 1
  • 17
  • 16
  • Thanks for the answer. It worked for me. But I have a request to shorten the URL. Is there any way to get rid of this part of the URL?: `_plugin/kibana/app/kibana#/dev_tools/console?_g=()` I tried adding the whole thing in an index.html page and put this in /etc/nginx/sites-enabled/elasticsearch. But when I checked this on the browser by giving only the IP address, it's showing the Elasticsearch cluster details. Please suggest me how I can achieve this. Thanks again. – Raghu Jun 06 '18 at 10:33
0

You may need to have IP-based policy and allow access to your domain from specific IP (Kibana's).

Other option (aside from changing access policy to be completely open) would be signing requests - IIRC this helped a friend of mine with similar message.

http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains.html#es-managedomains-signing-service-requests

See also "Connecting a Local Kibana Server to Amazon Elasticsearch Service" on the same page.