How do I use an NGINX proxy to access OpenSearch Dashboards from outside a VPC that's using Amazon Cognito authentication?

Last updated: 2021-10-26

My Amazon OpenSearch Service (successor to Amazon Elasticsearch Service) cluster is in a virtual private cloud (VPC). I want to use an NGINX proxy to access OpenSearch Dashboards from outside of the VPC with Amazon Cognito authentication. How can I do this?

Short description

Use NGINX to configure an Amazon Elastic Compute Cloud (Amazon EC2) instance as a proxy server. The proxy server then forwards browser requests to Amazon Cognito and OpenSearch Dashboards.

You can also use an SSH tunnel or Client VPN to access OpenSearch Dashboards from outside a VPC with Amazon Cognito authentication. For more information, see How can I use an SSH tunnel to access OpenSearch Dashboards from outside a VPC with Amazon Cognito authentication. For more information, see How can I use an SSH tunnel to access OpenSearch Dashboards from outside of a VPC with Amazon Cognito authentication?

Note: OpenSearch Dashboards is the successor to Kibana.

Resolution

Important: Your OpenSearch Services domain is more secure when you restrict access to users in the VPC. Before you continue, be sure that this procedure doesn't violate your organization's security requirements.

1.    Create an Amazon Cognito user pool.

2.    Configure a hosted user pool domain.

3.    In the Amazon Cognito console navigation pane, choose Users and groups.

4.    Choose Create user and then complete the fields. Be sure to enter an email address and select the Mark email as verified check box.

5.    Choose the Groups tab and then choose Create group. For Precedence, enter 0. For more information, see Creating a new group in the AWS Management Console.

6.    Open the Amazon Cognito console again.

7.    Choose Manage Identity Pools, and then choose Create new identity pool.

8.    Enter a name for your identity pool, select the check box to Enable access to unauthenticated identities, and then choose Create Pool.

9.    When you're prompted for access to your AWS resources, choose Allow to create the two default roles associated with your identity pool. Create one default role for unauthenticated users and create the other default role for authenticated users.

10.    Configure your OpenSearch Services domain to use Amazon Cognito authentication for OpenSearch Dashboards:
For Cognito User Pool, choose the user pool that you created.
For Cognito Identity Pool, choose the identity pool that you created.
For more information, see Get started with Amazon OpenSearch Service: Use Amazon Cognito for OpenSearch Dashboards access control.

11.    Configure your access policy so that it is a resource-based policy like the following:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::account-id:role/Cognito_identity-nameAuth_Role"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:region:aws-account-id:domain/domain-name/*"
    }
  ]
}

You must update these values:
account-id: your AWS account ID
identity-name: the name of your Amazon Cognito identity pool
ES-name: the name of your OpenSearch Services domain
region: the Region that your OpenSearch Service domain resides, such as us-east-1

12.    Launch an EC2 instance into a public subnet of the same VPC of your OpenSearch Services domain. Make sure that the instance uses the same security group as your domain.

13.    (Optional) If you're not using a test environment, then allocate an Elastic IP address to associate with the instance that you created. For more information about allocating Elastic IP addresses, see Work with Elastic IP addresses.

14.    (Optional) If you're not using a test environment, then configure your DNS to resolve requests to the Elastic IP address. For more information about how to resolve requests with Amazon Route 53, see Configuring Amazon Route 53 to route traffic to an Amazon EC2 instance.

15.    Connect to your instance and install NGINX.

For instances launched with an Amazon Linux 2 AMI, use the following command:

$ sudo amazon-linux-extras install nginx1

16.    Obtain an SSL certificate from a certificate authority (CA) to configure SSL for NGINX.

Note: If you're using a test environment, then generate a self-signed certificate instead. Self-signed certificates aren't trusted by browsers and shouldn't be used in production environments.

17.    (Optional) If you're using a test environment with a self-signed certificate, then use the OpenSSL x509 command to generate a private key:

$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/cert.key -out /etc/nginx/cert.crt

This command syntax generates cert.key, a private key for the self-signed SSL certificate.

18.    Navigate to the /etc/nginx/conf.d directory, and then create a file called default.conf. Modify the file with the following values:
/etc/nginx/cert.crt: the path to your SSL certificate
/etc/nginx/cert.key: the path to the private key that you generated for the SSL certificate
$domain-endpoint: your OpenSearch Services endpoint
$cognito_host: your Amazon Cognito user pool domain (that you configured in Step 2)

You can use the sed command to assign $domain-endpoint and $cognito_host as variables, instead of replacing them directly in the default.conf file. Additionally, make sure to use HTTPS, or you might encounter an error.

In this example, be aware of the following:

  • If your Amazon OpenSearch Service domain is running OpenSearch Service version 1.0+, use the _dashboards endpoint.
  • If your Amazon OpenSearch Service domain is running Elasticsearch versions 5.x-7.x, use the _plugin/kibana endpoint.
server {
    listen 443;
    server_name $host;
    rewrite ^/$ https://$host/_dashboards redirect;

    ssl_certificate           /etc/nginx/cert.crt;
    ssl_certificate_key       /etc/nginx/cert.key;

    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    location /_dashboards {
        # Forward requests to Dashboards
        proxy_pass https://$domain-endpoint/_dashboards;

        # Handle redirects to Cognito
        proxy_redirect https://$cognito_host https://$host;

        # Update cookie domain and path
        proxy_cookie_domain $domain-endpoint $host;
        proxy_cookie_path / /_dashboards/;

        # Response buffer settings
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }

    location ~ \/(log|sign|fav|forgot|change|saml|oauth2) {
        # Forward requests to Cognito
        proxy_pass https://$cognito_host;

        # Handle redirects to Dashboards
        proxy_redirect https://$domain-endpoint https://$host;

        # Update cookie domain
        proxy_cookie_domain $cognito_host $host;
    }
}

Important: The resolver parameter changes according to your VPC settings. The DNS resolver is located at your primary CIDR block's base IP plus two. For example, if you create a VPC with CIDR block 10.0.0.0/24, then your DNS resolver is located at 10.0.0.2.

19.    (Optional) Use the sed command to assign the $domain-endpoint and $cognito_host variables:

$ sudo sed -i 's/$domain-endpoint/vpc-mydashboards-111xxx.us-east1.es.amazonaws.com/' /etc/nginx/conf.d/default.conf
$ sudo sed -i 's/$cognito_host/mydomain.auth.us-east-1.amazoncognito.com/' /etc/nginx/conf.d/default.conf

Note: You don't have to replace $domain-endpoint and $cognito_host in the /etc/nginx/conf.d/default.conf file.

20.    Restart NGINX.

For instances launched with an Amazon Linux AMI, use this command:

$ sudo service nginx restart

For instances launched with an Amazon Linux 2 AMI, use this command:

$ sudo systemctl restart nginx.service

21.    Use your browser to access the NGINX IP or the DNS name. You're redirected to the Amazon Cognito login page.

22.    To log in to Dashboards, enter your user name and temporary password. Then, change your password when prompted, and log in again.