Skip to content

Decision: Configure the OpenSearch security plugin #51

@siegfriedweber

Description

@siegfriedweber

Description

The OpenSearch security plugin stores its configuration in a system index on the OpenSearch cluster. The initial configuration is taken from configuration files. Afterwards, the administrators can decide if they want to manage the configuration index via the OpenSearch API or overwrite it with updated configuration files. This decision can be made per configuration file.

The configuration files are (see also https://docs.opensearch.org/latest/security/configuration/yaml/):

  • action_groups.yml: groups permissions, e.g. the action group cluster_monitor could contain all actions which are required to monitor a cluster.
  • allowlist.yml: lists accessible API endpoints
  • audit.yml: contains the audit log configuration
  • config.yml: contains the configuration for authentication and authorization
  • internal_users.yml: contains "reserved" users like admin and kibanaserver (used by OpenSearch Dashboards)
  • nodes_dn.yml: can contain DNs of OpenSearch node certificates
  • roles_mapping.yml: maps OpenSearch roles to backend roles (e.g. LDAP roles) and users
  • roles.yml: assigns permissions to OpenSearch roles
  • tenants.yml: adds OpenSearch Dashboards tenants to OpenSearch

For instance, administrators probably want to use the operator to only apply the initial roles_mapping.yml but afterwards use the security plugin in OpenSearch Dashboards to manage it. On the other hand, the config.yml should probably be managed completely by the operator.

Part of #43

Solution in the OpenSearch Helm chart

The Helm chart only supports the initial deployment of the security configuration.

The configuration files can be in different secrets:

securityConfig:
  actionGroupsSecret: <string> # secret with the key "action_groups.yml"
  configSecret: <string> # secret with the key "config.yml"
  internalUsersSecret: <string> # secret with the key "internal_users.yml"
  rolesSecret: <string> # secret with the key "roles.yml"
  rolesMappingSecret: <string> # secret with the key "roles_mapping.yml"
  tenantsSecret: <string> # secret with the key "tenants.yml"

Or the configuration files can be taken from one secret:

securityConfig:
  config:
    securityConfigSecret: <string> # secret containing all configuration files

Or the configuration files can be defined inline:

securityConfig:
  config:
    dataComplete: <boolean> # If `true`, all configuration files are replace, otherwise only the given ones.
    data:
      config.yml: <string>
      internal_users.yml: <string>
      roles.yml: <string>
      roles_mapping.yml: <string>
      action_groups.yml: <string>
      tenants.yml: <string>

Solution in the OpenSearch Kubernetes Operator

The operator always manages the given configuration files. If the configuration files should only be initially applied and then managed by the OpenSearch API, the according configuration files must be removed from the secret.

spec:
  security:
    config:
      securityConfigSecret:
        name: <string> # The secret containing all or some configuration files; For the missing ones, the default configuration files are used.
      adminSecret:
        name: <string> # The secret containing the admin client certificate
      adminCredentialsSecret:
        name: <string> # The secret containing the admin credentials

Alternatively, users, roles, role bindings, action groups and tenants can be configured with dedicated custom resources:

apiVersion: opensearch.opster.io/v1
kind: OpensearchActionGroup
metadata:
  name: sample-action-group
spec:
  opensearchCluster:
    name: my-first-cluster
  allowedActions:
    - indices:admin/aliases/get
    - indices:admin/aliases/exists
  type: index
  description: Sample action group

This is very Kubernetes-like but users are often managed via LDAP and the other configurations via the API, so it is probably not so useful in larger enterprises.

Proposed solution for the Stackable OpenSearch operator

This proposal contains a general approach like configOverrides to cover all use cases. However, the current implementation of configOverrides is not sufficient because the mentioned YAML files contain deep structures. The security configuration only makes sense at the cluster level (not role or role-group level).

---
apiVersion: opensearch.stackable.tech/v1alpha1
kind: OpenSearchCluster
spec:
  clusterConfig:
    securityConfig:
      enabled: <boolean> # Enables or disables the security plugin; defaults to `true`
      actionGroups: # optional; defaults to an "empty" configuration file which only contains the necessary
                    # header
        managedBy: <string> # one of ["API", "operator"]; defaults to "API" for all configuration files
                            # because this is the default in OpenSearch, see
                            # https://docs.opensearch.org/latest/security/configuration/security-admin/#a-word-of-caution
        content: # one of ["value", "valueFrom"] similar to
                 # https://kubernetes.io/docs/concepts/configuration/configmap/#configmaps-and-pods
          value: <string> # file content
          valueFrom: # one of ["configMapKeyRef", "secretKeyRef"]
            configMapKeyRef:
              name: <string>
              key: <string>
            secretKeyRef: # Secrets are especially useful for `internal_users.yml` because it contains the
                          # bcrypted admin password
              name: <string>
              key: <string>
      allowList: <struct> # same structure as in `actionGroups`
      audit: <struct> # same structure as in `actionGroups`
      config: <struct> # same structure as in `actionGroups`
      internalUsers: <struct> # same structure as in `actionGroups`
      nodesDn: <struct> # same structure as in `actionGroups`
      rolesMapping: <struct> # same structure as in `actionGroups`
      roles: <struct> # same structure as in `actionGroups`
      tentants: <struct> # same structure as in `actionGroups`

It is not necessary to define the contents of all configuration files, because the "empty" default is already useful for actionGroups, allowList, audit, nodesDn, roles and tenants, and not so useful for config, internalUsers and rolesMapping. If nothing is configured, OpenSearch will start but it will not be accessible.

If the operator has the option to provide arbitrary security configurations, then it will be hard to integrate AuthenticationClasses later. If such an option is not provided, then the operator would probably be not useful in a lot of setups. Perhaps a solution could be to extend the structure for config.yml as follows:

spec:
  clusterConfig:
    securityConfig:
      config:
        enabled: <boolean>
        managedBy: <string> # one of ["API", "operator"]
        content: # one of ["value", "valueFrom"]
          value: <string>
          valueFrom: # one of ["configMapKeyRef", "secretKeyRef", "authenticationClasses"]
            configMapKeyRef:
              name: <string>
              key: <string>
            secretKeyRef:
              name: <string>
              key: <string>
            authenticationClasses: <list>
              - authenticationClass: <string>
                <additionalProperties>: ...

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions