Secure Elastic Services

Deploying secure Elastic services

Deploying a secure Elastic service

  1. Specify the name and settings for your Elastic and Kibana services. The names will be used in subsequent commands. If you have an existing Elastic or Kibana configuration JSON file, the values should match.

    service_name="elastic"
    kibana_service_name="kibana"
    service_account_name="${service_name}-service-account"
    secret_name="${service_name}-secret"
    virtual_network_enabled=true
    transport_encryption_enabled=true
    xpack_security_enabled=true
    elastic_options_file="elastic.json"
    kibana_options_file="kibana.json"
    
    protocol="$([ "${transport_encryption_enabled}" == "true" ] || [ "${xpack_security_enabled}" == "true" ] && echo "https" || echo "http")"
    kibana_elasticsearch_tls="$([ "${protocol}" == "https" ] && echo "true" || echo "false")"
    

    NOTE: HTTPS will be used either if elasticsearch.xpack_security_enabled or service.security.transport_encryption.enabled is true.

  2. Install Enterprise DC/OS CLI

    dcos package install --yes dcos-enterprise-cli
    
  3. Create keypair. This will create the elastic.private.pem and elastic.public.pem files. This step is not necessary if you already have a service account set up.

    dcos security org service-accounts keypair elastic.private.pem elastic.public.pem
    
  4. Create service account. This step is not necessary if you already have a service account set up for the Elastic service.

    dcos security org service-accounts create -p elastic.public.pem -d "${service_name} service account" "${service_account_name}"
    
  5. Create secret. This step is not necessary if you already have a secret set up for the Elastic service.

    dcos security secrets create-sa-secret elastic.private.pem "${service_account_name}" "${secret_name}"
    
  6. Grant necessary permissions to the service account. Check the DC/OS permissions reference documentation if you’d like to set permissions more granularly.

    dcos security org groups add_user superusers "${service_account_name}"
    
  7. Create Elastic configuration file. This step is not necessary if you already have a configuration file for Elastic, but make sure to verify it on the next step.

    cat <<EOF > "${elastic_options_file}"
    {
      "service": {
        "name": "${service_name}",
        "service_account": "${service_account_name}",
        "service_account_secret": "${secret_name}",
        "virtual_network_enabled": ${virtual_network_enabled},
        "virtual_network_name": "dcos",
        "security": {
          "transport_encryption": {
            "enabled": ${transport_encryption_enabled}
          }
        }
      },
      "elasticsearch": {
        "xpack_security_enabled": ${xpack_security_enabled}
      }
    }
    EOF
    
  8. The Elastic configuration file should look something like the following:

    cat "${elastic_options_file}"
    
    {
      "service": {
        "name": "elastic",
        "service_account": "elastic-service-account",
        "service_account_secret": "elastic-secret",
        "virtual_network_enabled": true,
        "virtual_network_name": "dcos",
        "security": {
          "transport_encryption": {
            "enabled": true
          }
        }
      },
      "elasticsearch": {
        "xpack_security_enabled": true
      }
    }
    
  9. Install Elastic with the given configuration:

    dcos package install --yes elastic --options="${elastic_options_file}"
    
  10. Wait for all pods to be RUNNING.

    dcos elastic --name "${service_name}" pod status
    
  11. Get master-0-node task ID and coordinator VIP endpoint.

    master_0_task_id="$(dcos elastic --name="${service_name}" pod info master-0 | jq -r '.[0].info.taskId.value')"
    master_0_task_dns="$(dcos elastic --name="${service_name}" endpoints master-http | jq -r '.dns[0]')"
    coordinator_vip="$(dcos elastic --name="${service_name}" endpoints coordinator-http | jq -r '.vip')"
    
  12. Set up initial passwords.

    dcos task exec "${master_0_task_id}" bash -c "
      set -x
      export JAVA_HOME=\$(ls -d \${MESOS_SANDBOX}/jdk*)
      ELASTICSEARCH_PATH=\$(ls -d \${MESOS_SANDBOX}/elasticsearch-*/)
      \${ELASTICSEARCH_PATH}/bin/elasticsearch-setup-passwords auto --batch --verbose --url ${protocol}://${master_0_task_dns}
    " | tee -a elasticsearch_setup_passwords_output.txt
    
  13. Extract initial credentials.

    elastic_password=$(grep 'PASSWORD elastic' elasticsearch_setup_passwords_output.txt | awk -F' = ' '{print $2}' | tail -n1)
    kibana_password=$(grep 'PASSWORD kibana' elasticsearch_setup_passwords_output.txt | awk -F' = ' '{print $2}' | tail -n1)
    
  14. Configure Elastic with initial credentials.

    dcos elastic --name "${service_name}" update start --options=<(echo "{
      \"elasticsearch\": {\"health_user_password\": \"${elastic_password}\"}
    }")
    
  15. Wait for the update to complete.

    dcos elastic --name "${service_name}" update status
    
  16. Get master-0-node task ID again. After the update completes, a new master-0-node task will be running. Let’s get the task ID for it.

    master_0_task_id="$(dcos elastic --name="${service_name}" pod info master-0 | jq -r '.[0].info.taskId.value')"
    
  17. Test access with credentials. The Elasticsearch cluster should be available now, given that requests include credentials.

    dcos task exec "${master_0_task_id}" \
        /opt/mesosphere/bin/curl -si \
        -u "elastic:${elastic_password}" \
        -H 'Content-type: application/json' \
        "${protocol}://${coordinator_vip}/_cluster/health?pretty"
    
  18. Create Kibana configuration file. This step is not necessary if you already have a configuration file for Kibana, but make sure to verify it on the next step. It is important that the password setting is configured with the Kibana password returned from the “set up initial passwords” step above.

    cat <<EOF > "${kibana_options_file}"
    {
      "service": {
        "name": "${kibana_service_name}"
      },
      "kibana": {
        "elasticsearch_tls": ${kibana_elasticsearch_tls},
        "elasticsearch_url": "${protocol}://${coordinator_vip}",
        "password": "${kibana_password}"
      }
    }
    EOF
    

    The Kibana configuration file should look something like the following

    cat "${kibana_options_file}"
    
    {
      "service": {
        "name": "kibana"
      },
      "kibana": {
        "elasticsearch_tls": true,
        "elasticsearch_url": "https://coordinator.elastic.l4lb.thisdcos.directory:9200",
        "password": "..."
      }
    }
    
  19. Install Kibana with given configuration:

    dcos package install kibana --yes --options="${kibana_options_file}"
    
  20. Wait for Kibana to finish deploying. The following command will output 1 when that happens.

    dcos marathon app show "${kibana_service_name}" | jq -r '.tasksHealthy'
    

(Optional) Verify the current license

This should be a new Elasticsearch installation, so the cluster will be running under a “basic” license unless it was changed. You might want to install an actual license. In this guide we will start a trial license.

dcos task exec "${master_0_task_id}" \
     /opt/mesosphere/bin/curl -si \
     -u "elastic:${elastic_password}" \
     -H 'Content-type: application/json' \
     "${protocol}://${master_0_task_dns}/_xpack/license?pretty"

(Optional) Start trial license

dcos task exec "${master_0_task_id}" \
     /opt/mesosphere/bin/curl -si \
     -XPOST \
     -u "elastic:${elastic_password}" \
     -H 'Content-type: application/json' \
     "${protocol}://${coordinator_vip}/_xpack/license/start_trial?acknowledge=true&pretty"

That’s it! Assuming all steps worked, you should have a secure deployment of Elasticsearch and Kibana. From here you can use the Elasticsearch APIs to change passwords, manage users, permissions and roles.

If you change passwords, don’t forget to update the Elastic service with the health-check credentials as was done in the “Configure Elastic with initial credentials” step.

For more details check out the Elasticsearch security documentation.