---
type: api
title: Create or update roles
description: **All methods and paths for this operation:**
url: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/elasticsearch/operation/operation-security-put-role
resource: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/elasticsearch/operation/operation-security-put-role
products:
  - Elasticsearch
---

# Create or update roles


Availability:

## Paths

- `POST` (also `PUT`) `/_security/role/{name}`

- [Api key auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/authentication#apikeyauth)
- [Basic auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/authentication#basicauth)
- [Bearer auth](/elastic/docs-builder/docs/4371/api/doc/elasticsearch/authentication#bearerauth)

#### Path Parameters

- `name` (string Name)
  The name of the role that is being created or updated. On Elasticsearch Serverless, the role name must begin with a letter or digit and can only contain letters, digits and the characters '_', '-', and '.'. Each role must have a unique name, as this will serve as the identifier for that role.

## Description

The role management APIs are generally the preferred way to manage roles in the native realm, rather than using file-based role management.
The create or update roles API cannot update roles that are defined in roles files.
File-based role management is not available in Elastic Serverless.

## Required authorization

* Cluster privileges: `manage_security`

[More about defining roles](https://www.elastic.co/docs/deploy-manage/users-roles/cluster-or-deployment-auth/defining-roles)

## Query String Parameters

- `refresh` (enum Refresh)
  If `true` (the default) then refresh the affected shards to make this operation visible to search, if `wait_for` then wait for a refresh to make this operation visible to search, if `false` then do nothing with refreshes.
  Values: `true`, `false`, `wait_for`

## Request Body

`application/json`

- `applications` ([] ApplicationPrivileges) — optional
  A list of application privilege entries.
  - `application` (string) — required
    The name of the application to which this entry applies.
  - `privileges` ([] string) — required
    A list of strings, where each element is the name of an application privilege or action.
  - `resources` ([] string) — required
    A list resources to which the privileges are applied.
- `cluster` ([] union ClusterPrivilege) — optional
  A list of cluster privileges. These privileges define the cluster-level actions for users with this role.
  Values: `all`, `cancel_task`, `clone_api_key`, `create_snapshot`, `cross_cluster_replication`, `cross_cluster_search`, `delegate_pki`, `grant_api_key`, `manage`, `manage_api_key`, `manage_autoscaling`, `manage_behavioral_analytics`, `manage_ccr`, `manage_data_frame_transforms`, `manage_data_stream_global_retention`, `manage_enrich`, `manage_esql`, `manage_ilm`, `manage_index_templates`, `manage_inference`, `manage_ingest_pipelines`, `manage_logstash_pipelines`, `manage_ml`, `manage_oidc`, `manage_own_api_key`, `manage_pipeline`, `manage_reindex`, `manage_rollup`, `manage_saml`, `manage_search_application`, `manage_search_query_rules`, `manage_search_synonyms`, `manage_security`, `manage_service_account`, `manage_slm`, `manage_token`, `manage_transform`, `manage_user_profile`, `manage_watcher`, `monitor`, `monitor_data_frame_transforms`, `monitor_data_stream_global_retention`, `monitor_enrich`, `monitor_esql`, `monitor_inference`, `monitor_ml`, `monitor_reindex`, `monitor_rollup`, `monitor_snapshot`, `monitor_stats`, `monitor_text_structure`, `monitor_transform`, `monitor_watcher`, `none`, `post_behavioral_analytics_event`, `read_ccr`, `read_fleet_secrets`, `read_ilm`, `read_pipeline`, `read_security`, `read_slm`, `transport_client`, `write_connector_secrets`, `write_fleet_secrets`
- `global` (map string to object) — optional
  An object defining global privileges. A global privilege is a form of cluster privilege that is request-aware. Support for global privileges is currently limited to the management of application privileges.
- `indices` ([] IndicesPrivileges) — optional
  A list of indices permissions entries.
  - `field_security` ({} FieldSecurity) — optional
    The document fields that the owners of the role have read access to.
    - `except` (string Fields) — optional
    - `grant` (string Fields) — optional
  - `names` (union IndexName | [] IndexName) — required
    A list of indices (or index name patterns) to which the permissions in this entry apply.
  - `privileges` ([] union IndexPrivilege) — required
    The index level privileges that owners of the role have on the specified indices.
    Values: `all`, `auto_configure`, `create`, `create_doc`, `create_index`, `create_view`, `cross_cluster_replication`, `cross_cluster_replication_internal`, `delete`, `delete_index`, `delete_view`, `index`, `maintenance`, `manage`, `manage_data_stream_lifecycle`, `manage_follow_index`, `manage_ilm`, `manage_leader_index`, `manage_view`, `monitor`, `none`, `read`, `read_cross_cluster`, `read_view_metadata`, `view_index_metadata`, `write`
  - `query` (IndicesPrivilegesQuery) — optional
    A search query that defines the documents the owners of the role have access to. A document within the specified indices must match this query for it to be accessible by the owners of the role.
  - `allow_restricted_indices` (boolean · default: false) — optional
    Set to `true` if using wildcard or regular expressions for patterns that cover restricted indices. Implicitly, restricted indices have limited privileges that can cause pattern tests to fail. If restricted indices are explicitly included in the `names` list, Elasticsearch checks privileges against these indices regardless of the value set for `allow_restricted_indices`.
- `remote_indices` ([] RemoteIndicesPrivileges) — optional
  A list of remote indices permissions entries.

NOTE: Remote indices are effective for remote clusters configured with the API key based model.
They have no effect for remote clusters configured with the certificate based model.
  - `clusters` (string Names) — required
    A list of cluster aliases to which the permissions in this entry apply.
  - `field_security` ({} FieldSecurity) — optional
    The document fields that the owners of the role have read access to.
    - `except` (string Fields) — optional
    - `grant` (string Fields) — optional
  - `names` (union IndexName | [] IndexName) — required
    A list of indices (or index name patterns) to which the permissions in this entry apply.
  - `privileges` ([] union IndexPrivilege) — required
    The index level privileges that owners of the role have on the specified indices.
    Values: `all`, `auto_configure`, `create`, `create_doc`, `create_index`, `create_view`, `cross_cluster_replication`, `cross_cluster_replication_internal`, `delete`, `delete_index`, `delete_view`, `index`, `maintenance`, `manage`, `manage_data_stream_lifecycle`, `manage_follow_index`, `manage_ilm`, `manage_leader_index`, `manage_view`, `monitor`, `none`, `read`, `read_cross_cluster`, `read_view_metadata`, `view_index_metadata`, `write`
  - `query` (IndicesPrivilegesQuery) — optional
    A search query that defines the documents the owners of the role have access to. A document within the specified indices must match this query for it to be accessible by the owners of the role.
  - `allow_restricted_indices` (boolean · default: false) — optional
    Set to `true` if using wildcard or regular expressions for patterns that cover restricted indices. Implicitly, restricted indices have limited privileges that can cause pattern tests to fail. If restricted indices are explicitly included in the `names` list, Elasticsearch checks privileges against these indices regardless of the value set for `allow_restricted_indices`.
- `remote_cluster` ([] RemoteClusterPrivileges) — optional
  A list of remote cluster permissions entries.
  - `clusters` (string Names) — required
    A list of cluster aliases to which the permissions in this entry apply.
  - `privileges` ([] enum RemoteClusterPrivilege) — required
    The cluster level privileges that owners of the role have on the remote cluster.
    Values: `monitor_enrich`, `monitor_stats`
- `metadata` (Metadata) — optional
  Optional metadata. Within the metadata object, keys that begin with an underscore (`_`) are reserved for system use.
- `run_as` ([] string) — optional
  A list of users that the owners of this role can impersonate. *Note*: in Serverless, the run-as feature is disabled. For API compatibility, you can still specify an empty `run_as` field, but a non-empty list will be rejected.
- `description` (string) — optional
  Optional description of the role descriptor
- `transient_metadata` (map string to object) — optional
  Indicates roles that might be incompatible with the current cluster license, specifically roles with document and field level security. When the cluster license doesn’t allow certain features for a given role, this parameter is updated dynamically to list the incompatible features. If `enabled` is `false`, the role is ignored, but is still listed in the response from the authenticate API.

## Response

`application/json`

- `role` ({} CreatedStatus)
  When an existing role is updated, `created` is set to `false`.
  - `created` (boolean)
## Code Examples

#### Console

```console
POST /_security/role/my_admin_role
{
  "description": "Grants full access to all management features within the cluster.",
  "cluster": ["all"],
  "indices": [
    {
      "names": [ "index1", "index2" ],
      "privileges": ["all"],
      "field_security" : { // optional
        "grant" : [ "title", "body" ]
      },
      "query": "{\"match\": {\"title\": \"foo\"}}" // optional
    }
  ],
  "applications": [
    {
      "application": "myapp",
      "privileges": [ "admin", "read" ],
      "resources": [ "*" ]
    }
  ],
  "run_as": [ "other_user" ], // optional
  "metadata" : { // optional
    "version" : 1
  }
}
```

#### JavaScript

```javascript
const response = await client.security.putRole({
  name: "my_admin_role",
  description:
    "Grants full access to all management features within the cluster.",
  cluster: ["all"],
  indices: [
    {
      names: ["index1", "index2"],
      privileges: ["all"],
      field_security: {
        grant: ["title", "body"],
      },
      query: '{"match": {"title": "foo"}}',
    },
  ],
  applications: [
    {
      application: "myapp",
      privileges: ["admin", "read"],
      resources: ["*"],
    },
  ],
  run_as: ["other_user"],
  metadata: {
    version: 1,
  },
});
```

#### Python

```python
resp = client.security.put_role(
    name="my_admin_role",
    description="Grants full access to all management features within the cluster.",
    cluster=[
        "all"
    ],
    indices=[
        {
            "names": [
                "index1",
                "index2"
            ],
            "privileges": [
                "all"
            ],
            "field_security": {
                "grant": [
                    "title",
                    "body"
                ]
            },
            "query": "{\"match\": {\"title\": \"foo\"}}"
        }
    ],
    applications=[
        {
            "application": "myapp",
            "privileges": [
                "admin",
                "read"
            ],
            "resources": [
                "*"
            ]
        }
    ],
    run_as=[
        "other_user"
    ],
    metadata={
        "version": 1
    },
)
```

#### curl

```curl
curl -X POST "$ELASTICSEARCH_URL/_security/role/my_admin_role" \
  -H "Authorization: ApiKey $ELASTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Grants full access to all management features within the cluster.",
    "cluster": [
      "all"
    ],
    "indices": [
      {
        "names": [
          "index1",
          "index2"
        ],
        "privileges": [
          "all"
        ],
        "field_security": {
          "grant": [
            "title",
            "body"
          ]
        },
        "query": "{\u0022match\u0022: {\u0022title\u0022: \u0022foo\u0022}}"
      }
    ],
    "applications": [
      {
        "application": "myapp",
        "privileges": [
          "admin",
          "read"
        ],
        "resources": [
          "*"
        ]
      }
    ],
    "run_as": [
      "other_user"
    ],
    "metadata": {
      "version": 1
    }
  }'
```

#### Java

```java
client.security().putRole(p -> p
    .applications(a -> a
        .application("myapp")
        .privileges(List.of("admin","read"))
        .resources("*")
    )
    .cluster("all")
    .description("Grants full access to all management features within the cluster.")
    .indices(i -> i
        .fieldSecurity(f -> f
            .grant(List.of("title","body"))
        )
        .names(List.of("index1","index2"))
        .privileges("all")
        .query(q -> q
            .match(m -> m
                .field("title")
                .query(FieldValue.of("foo"))
            )
        )
    )
    .metadata("version", JsonData.fromJson("1"))
    .name("my_admin_role")
    .runAs("other_user")
);
```

#### C#

```c#
var response = await client.Security
    .PutRoleAsync(name: "my_admin_role", d1 => d1
        .Applications(d2 => d2
            .Application("myapp")
            .Privileges("admin", "read")
            .Resources("*")
        )
        .Cluster(ClusterPrivilege.All)
        .Description("Grants full access to all management features within the cluster.")
        .Indices(d2 => d2
            .FieldSecurity(d3 => d3
                .Grant(x => x.Title, x => x.Body)
            )
            .Names(["index1", "index2"])
            .Privileges(IndexPrivilege.All)
            .Query("{\"match\": {\"title\": \"foo\"}}")
        )
        .Metadata(new Dictionary<string, object>()
        {
            { "version", 1 }
        })
        .RunAs("other_user")
    );
```

#### PHP

```php
$resp = $client->security()->putRole([
    "name" => "my_admin_role",
    "body" => [
        "description" => "Grants full access to all management features within the cluster.",
        "cluster" => array(
            "all",
        ),
        "indices" => array(
            [
                "names" => array(
                    "index1",
                    "index2",
                ),
                "privileges" => array(
                    "all",
                ),
                "field_security" => [
                    "grant" => array(
                        "title",
                        "body",
                    ),
                ],
                "query" => "{\"match\": {\"title\": \"foo\"}}",
            ],
        ),
        "applications" => array(
            [
                "application" => "myapp",
                "privileges" => array(
                    "admin",
                    "read",
                ),
                "resources" => array(
                    "*",
                ),
            ],
        ),
        "run_as" => array(
            "other_user",
        ),
        "metadata" => [
            "version" => 1,
        ],
    ],
]);
```

#### Ruby

```ruby
response = client.security.put_role(
  name: "my_admin_role",
  body: {
    "description": "Grants full access to all management features within the cluster.",
    "cluster": [
      "all"
    ],
    "indices": [
      {
        "names": [
          "index1",
          "index2"
        ],
        "privileges": [
          "all"
        ],
        "field_security": {
          "grant": [
            "title",
            "body"
          ]
        },
        "query": "{\"match\": {\"title\": \"foo\"}}"
      }
    ],
    "applications": [
      {
        "application": "myapp",
        "privileges": [
          "admin",
          "read"
        ],
        "resources": [
          "*"
        ]
      }
    ],
    "run_as": [
      "other_user"
    ],
    "metadata": {
      "version": 1
    }
  }
)
```

## Response Examples

#### Security put role response example1

A successful response from `POST /_security/role/my_admin_role`.

```json
{
  "role": {
    "created": true 
  }
}
```

