Creating dedicated Elasticsearch users and roles keeps API clients, ingest components, and human operators off the built-in elastic superuser and makes least-privilege access practical for daily cluster work.
Native users and roles are stored in the .security index and are managed through the _security/user and _security/role APIs. Roles bundle cluster privileges such as monitor with index privileges such as read or view_index_metadata, and a user receives the combined privileges from every assigned role.
Creating or updating either object requires an authenticated account with the manage_security cluster privilege. The built-in elastic user is best treated as a bootstrap account for creating narrower native users, and self-managed clusters that use a private HTTP CA may require curl to trust that CA or use --cacert /path/to/http_ca.crt before the API calls succeed.
$ curl --silent --show-error --fail --user elastic "https://localhost:9200/_security/_authenticate?pretty"
Enter host password for user 'elastic':
{
"username" : "elastic",
"roles" : [
"superuser"
],
"full_name" : null,
"email" : null,
"metadata" : {
"_reserved" : true
},
"enabled" : true,
"authentication_realm" : {
"name" : "reserved",
"type" : "reserved"
},
"lookup_realm" : {
"name" : "reserved",
"type" : "reserved"
},
"authentication_type" : "realm"
}
Use any account that already has manage_security, and keep elastic for bootstrap-only administration where possible.
$ curl --silent --show-error --fail --user elastic -H "Content-Type: application/json" -X PUT "https://localhost:9200/_security/role/logs_reader?pretty" -d '{
"cluster" : ["monitor"],
"indices" : [
{
"names" : ["logs-*"],
"privileges" : ["read", "view_index_metadata"]
}
]
}'
Enter host password for user 'elastic':
{
"role" : {
"created" : true
}
}
Reuse the same role name with PUT to update the stored privilege set, and keep index patterns and privileges as narrow as the workload allows.
$ curl --silent --show-error --fail --user elastic "https://localhost:9200/_security/role/logs_reader?pretty"
Enter host password for user 'elastic':
{
"logs_reader" : {
"cluster" : [
"monitor"
],
"indices" : [
{
"names" : [
"logs-*"
],
"privileges" : [
"read",
"view_index_metadata"
],
"allow_restricted_indices" : false
}
],
"applications" : [ ],
"run_as" : [ ],
"metadata" : { },
"transient_metadata" : {
"enabled" : true
}
}
}
Checking the saved role first makes it easier to catch an over-broad wildcard or a missing cluster privilege before the user starts authenticating with it.
$ curl --silent --show-error --fail --user elastic -H "Content-Type: application/json" -X PUT "https://localhost:9200/_security/user/logs-viewer?pretty" -d '{
"password" : "ChangeMe-LogsViewer-92!",
"roles" : ["logs_reader"],
"full_name" : "Logs Viewer"
}'
Enter host password for user 'elastic':
{
"created" : true
}
Replace the sample password before running the request, and avoid saving reusable credentials in shell history, scripts, or ticket notes.
$ curl --silent --show-error --fail --user logs-viewer "https://localhost:9200/_security/_authenticate?pretty"
Enter host password for user 'logs-viewer':
{
"username" : "logs-viewer",
"roles" : [
"logs_reader"
],
"full_name" : "Logs Viewer",
"email" : null,
"metadata" : { },
"enabled" : true,
"authentication_realm" : {
"name" : "default_native",
"type" : "native"
},
"lookup_realm" : {
"name" : "default_native",
"type" : "native"
},
"authentication_type" : "realm"
}
The default_native realm in the response confirms that the account is being served from the native realm rather than from the reserved built-in user set.
$ curl --silent --show-error --fail --user logs-viewer "https://localhost:9200/_security/user/_privileges?pretty"
Enter host password for user 'logs-viewer':
{
"cluster" : [
"monitor"
],
"global" : [ ],
"indices" : [
{
"names" : [
"logs-*"
],
"privileges" : [
"read",
"view_index_metadata"
],
"allow_restricted_indices" : false
}
],
"applications" : [ ],
"run_as" : [ ]
}
This API only reports the privileges of the currently authenticated user, which makes it a direct least-privilege check after the role assignment.