# Configuration for setting up resources in Keycloak to enable OIDC authentication.
# Prerequisite: Ensure that the Keycloak Operator is installed and integrated with Keycloak.
# Refer to the installation guide for the Keycloak Operator:
# https://github.com/epam/edp-cluster-add-ons/tree/main/clusters/core/addons/keycloak-operator
#
# Additionally, necessary Keycloak resources such as realms, roles, and groups must be created
# to support component functionality. This can be done using the provided add-ons or manually:
# https://github.com/epam/edp-cluster-add-ons/tree/main/clusters/core/addons/kuberocketci-rbac
oidc:
  enabled: true
  dashboardUrl: https://opensearch-dashboards.example.com

# This section enables configuration for using External Secrets Operator (ESO) as the secret manager.
# Prerequisite: Ensure that ESO is installed in the cluster.
# Refer to the EDP cluster add-on for ESO installation and setup:
# https://github.com/epam/edp-cluster-add-ons/tree/main/clusters/core/addons/external-secrets
#
# Ensure that you have created the necessary roles for ESO integration.
# Follow the detailed instructions here:
# https://docs.kuberocketci.io/docs/operator-guide/secrets-management/external-secrets-operator-integration#aws-parameter-store-scenario-in-kuberocketci
eso:
  # -- Install components of the ESO.
  enabled: true
  # -- Defines provider type. One of `aws` or `generic`.
  type: "aws"
  # -- Defines Secret Store name.
  secretStoreName: "aws-parameterstore"
  # -- Value name in AWS ParameterStore, AWS SecretsManager or other Secret Store.
  secretName: "/infra/core/addons/opensearch"
  # -- Role ARN for the ExternalSecretOperator to assume.
  roleArn: arn:aws:iam::012345678910:role/AWSIRSA_Shared_ExternalSecretOperatorAccess
  # Defines Secret Store configuration. Used when eso.type is set to "generic".
  generic:
    secretStore:
      # -- Defines SecretStore provider configuration.
      providerConfig: {}
      #  gcpsm:
      #    projectID: "alphabet-123"

opensearch:
  nameOverride: "opensearch"
  fullnameOverride: "opensearch"

  singleNode: true

  resources:
    requests:
      cpu: "500m"
      memory: "1024Mi"

  persistence:
    storageClass: "ebs-sc"
    # Set to false to disable the `fsgroup-volume` initContainer that will update permissions on the persistent disk.
    enableInitChown: false

  config:
    opensearch.yml: |
      cluster.name: opensearch-cluster

      # Bind to all interfaces because we don't know what IP address Docker will assign to us.
      network.host: 0.0.0.0

      # # minimum_master_nodes need to be explicitly set when bound on a public IP
      # # set to 1 to allow single node clusters
      # discovery.zen.minimum_master_nodes: 1

      # Setting network.host to a non-loopback address enables the annoying bootstrap checks. "Single-node" mode disables them again.
      #discovery.type: single-node

      ######## Start OpenSearch Security Demo Configuration ########
      # WARNING: revise all the lines below before you go into production
      plugins:
        security:
          nodes_dn:
            - 'CN=opensearch.cluster.local'
          ssl:
            transport:
              pemcert_filepath: certs/tls.crt
              pemkey_filepath: certs/tls.key
              pemtrustedcas_filepath: certs/ca.crt
              enforce_hostname_verification: false
            http:
              enabled: true
              pemcert_filepath: certs/tls.crt
              pemkey_filepath: certs/tls.key
              pemtrustedcas_filepath: certs/ca.crt
          allow_unsafe_democertificates: false
          allow_default_init_securityindex: true
          authcz:
            admin_dn:
              - 'CN=admin'
          audit.type: internal_opensearch
          enable_snapshot_restore_privilege: true
          check_snapshot_restore_write_privileges: true
          restapi:
            roles_enabled: ["all_access", "security_rest_api_access"]
          system_indices:
            enabled: true
            indices:
              [
                ".opendistro-alerting-config",
                ".opendistro-alerting-alert*",
                ".opendistro-anomaly-results*",
                ".opendistro-anomaly-detector*",
                ".opendistro-anomaly-checkpoints",
                ".opendistro-anomaly-detection-state",
                ".opendistro-reports-*",
                ".opendistro-notifications-*",
                ".opendistro-notebooks",
                ".opendistro-asynchronous-search-response*",
              ]
      ######## End OpenSearch Security Demo Configuration ########

  extraEnvs:
    - name: DISABLE_INSTALL_DEMO_CONFIG
      value: "true"

  secretMounts:
    - name: opensearch-certs
      secretName: tls-for-opensearch-key-pair
      path: /usr/share/opensearch/config/certs
    - name: opensearch-admin-certs
      secretName: tls-for-opensearch-admin-key-pair
      path: /usr/share/opensearch/config/admin-certs

  securityConfig:
    enabled: true
    path: "/usr/share/opensearch/config/opensearch-security"
    actionGroupsSecret:
    configSecret:
    internalUsersSecret:
    rolesSecret:
    rolesMappingSecret:
    tenantsSecret:
    # The following option simplifies securityConfig by using a single secret and
    # specifying the config files as keys in the secret instead of creating
    # different secrets for each config file.
    # Note that this is an alternative to the individual secret configuration
    # above and shouldn't be used if the above secrets are used.
    config:
      # There are multiple ways to define the configuration here:
      # * If you define anything under data, the chart will automatically create
      #   a secret and mount it.
      # * If you define securityConfigSecret, the chart will assume this secret is
      #   created externally and mount it.
      # * It is an error to define both data and securityConfigSecret.
      securityConfigSecret: ""
      data:
        action_groups.yml: |-
          _meta:
            type: "actiongroups"
            config_version: 2
        config.yml: |-
          _meta:
            type: "config"
            config_version: 2
          config:
            dynamic:
              http:
                anonymous_auth_enabled: false
                xff:
                  enabled: false
                  internalProxies: "192\\.168\\.0\\.10|192\\.168\\.0\\.11"
              authc:
                basic_internal_auth_domain:
                  description: "Authenticate via HTTP Basic against internal users database"
                  http_enabled: true
                  transport_enabled: true
                  order: 0
                  http_authenticator:
                    type: basic
                    challenge: false
                  authentication_backend:
                    type: internal

                openid_auth_domain:
                  http_enabled: true
                  transport_enabled: true
                  order: 1
                  http_authenticator:
                    type: openid
                    challenge: false
                    config:
                      subject_key: preferred_username
                      roles_key: roles
                      openid_connect_url: https://keycloak.example.com/auth/realms/shared/.well-known/openid-configuration
                      openid_connect_idp:
                        enable_ssl: false
                        verify_hostnames: false
                  authentication_backend:
                    type: noop

        internal_users.yml: |-
          _meta:
            type: "internalusers"
            config_version: 2
          admin:
            hash: "CONSULT OpenSearch FOR HASHED PASSWORD"
            reserved: true
            hidden: false
            backend_roles:
            - "admin"
            attributes: {}
            description: "Demo admin user"
            static: false
          kibanaserver:
            hash: "CONSULT OpenSearch FOR HASHED PASSWORD"
            reserved: true
            hidden: false
            backend_roles: []
            attributes: {}
            description: "Kibanaserver user"
            static: false
          logstash:
            hash: "CONSULT OpenSearch FOR HASHED PASSWORD"
            reserved: false
            hidden: false
            backend_roles:
            - "logstash"
            attributes: {}
            description: "Log injection user"
            static: false
        nodes_dn.yml: |-
          _meta:
            type: "nodesdn"
            config_version: 2
          trustednodes:
            nodes_dn:
              - "CN=opensearch.cluster.local"
        roles_mapping.yml: |-
          _meta:
            type: "rolesmapping"
            config_version: 2
          all_access:
            reserved: true
            backend_roles:
            - "administrator"
            - "admin"
            description: "Maps EDP administrator role and internal admin role to all_access"
          logstash:
            reserved: true
            backend_roles:
            - "logstash"
            description: "Maps log injection role to logstash. It might be logstash, fluent-bit, fluentd, ..."
          kibana_user:
            reserved: false
            backend_roles:
            - "kibanauser"
            - "developer"
            description: "Maps kibanauser and EDP developer role to kibana_user"
          kibana_server:
            reserved: true
            users:
            - "kibanaserver"
          edp_developer:
            reserved: false
            backend_roles:
            - "developer"
            description: "Maps EDP developer role to view kube index"
        roles.yml: |-
          _meta:
            type: "roles"
            config_version: 2
          edp_developer:
            reserved: false
            hidden: false
            cluster_permissions: []
            index_permissions:
              - index_patterns:
                  - "logstash-edp*"
                allowed_actions:
                  - "indices:data/read/*"
            tenant_permissions:
              - tenant_patterns:
                  - "*"
                allowed_actions:
                  - "kibana:discover/*"
        tenants.yml: |-
          _meta:
            type: "tenants"
            config_version: 2
          admin_tenant:
            reserved: false
            description: "Demo tenant for admin user"
        whitelist.yml: |-
          _meta:
            type: "whitelist"
            config_version: 2

opensearch-dashboards:
  nameOverride: "opensearch-dashboards"
  fullnameOverride: "opensearch-dashboards"
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - host: kibana.example.com
        paths:
          - path: /
            backend:
              serviceName: ""
              servicePort: ""

  secretMounts:
    - name: opensearch-certs
      secretName: tls-for-dashboards-key-pair
      path: /usr/share/opensearch-dashboards/certs

  extraEnvs:
    - name: OIDC_CLIENT_SECRET
      valueFrom:
        secretKeyRef:
          # ensure this secret name is equal to the secret name in opensearchAccount section
          name: opensearch-dashboards-account
          key: OIDC_CLIENT_SECRET

  opensearchAccount:
    secret: "opensearch-dashboards-account"
    keyPassphrase:
      enabled: false

  config:
    opensearch_dashboards.yml:
      server:
        #name: dashboards
        host: 0.0.0.0

        ssl:
          # we disable ssl with self-signed certs, because we are behind alb+nginx
          enabled: false
          key: /usr/share/opensearch-dashboards/certs/tls.key
          certificate: /usr/share/opensearch-dashboards/certs/tls.crt

      opensearch:
        ssl:
          verificationMode: certificate
          certificateAuthorities: /usr/share/opensearch-dashboards/certs/ca.crt
        username: ${OPENSEARCH_USERNAME}
        password: ${OPENSEARCH_PASSWORD}
        requestHeadersAllowlist: ["Authorization", "security_tenant"]

      opensearch_security:
        multitenancy:
          enabled: true
          tenants.enable_global: true
          tenants.enable_private: true
          tenants.preferred: ["Private", "Global"]
          enable_filter: false
        cookie:
          secure: false
          password: ${COOKIE_PASS}

        auth.type: openid
        openid:
          connect_url: https://keycloak.example.com/auth/realms/shared/.well-known/openid-configuration
          base_redirect_url: https://kibana.example.com
          client_id: opensearch
          client_secret: ${OIDC_CLIENT_SECRET}
          scope: openid profile email
          header: Authorization
          # root_ca: /usr/share/opensearch-dashboards/config/certificates/ca/ca.pem
          verify_hostnames: false
          trust_dynamic_headers: true
  # Example logic for create index pattern
  # lifecycle:
  #   postStart:
  #     exec:
  #       command:
  #       - bash
  #       - -c
  #       - |
  #         #!/usr/bin/bash
  #         # Config the index_pattern
  #         INDEX_PATTERN="logstash-edp*"
  #         OPENSEARCH_DASHBOARD=http://localhost:5601
  #         # Wait until service is ready
  #         while [ "$(curl -s -o /dev/null -w '%{http_code}\n' $OPENSEARCH_DASHBOARD/app/kibana)" != "302" ]; do
  #           sleep 1
  #         done
  #         # Apply Index Pattern into Kibana
  #         curl -X POST $OPENSEARCH_DASHBOARD/api/saved_objects/index-pattern \
  #           -u $OPENSEARCH_USERNAME:$OPENSEARCH_PASSWORD \
  #           -H 'osd-xsrf: true' \
  #           -H 'Content-Type: application/json' \
  #           -d '{"attributes":{"title": "'$INDEX_PATTERN'"}}'

  startupProbe:
    # let's give more time for opensearch to start
    initialDelaySeconds: 60

fluent-bit:
  testFramework:
    enabled: false
  env:
    - name: ES_SUPERUSER_USER
      valueFrom:
        secretKeyRef:
          name: fluentbit-creds
          key: username
    - name: ES_SUPERUSER_PASSWORD
      valueFrom:
        secretKeyRef:
          name: fluentbit-creds
          key: password
  config:
    customParsers: |
      [PARSER]
          Name docker_no_time
          Format json
          Time_Keep Off
          Time_Key time
          Time_Format %Y-%m-%dT%H:%M:%S.%L

      [PARSER]
          Name        java_multiline
          Format      regex
          Regex       /^(?<time>\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}) (?<level>[^\s]+)(?<message>.*)/
          Time_Key    time
          Time_Format %Y-%m-%d %H:%M:%S

    inputs: |
      [INPUT]
          Name tail
          Path /var/log/containers/*.log
          multiline.parser docker, cri
          Tag kube.*
          Mem_Buf_Limit 5MB
          Skip_Long_Lines On

      [INPUT]
          Name systemd
          Tag host.*
          Systemd_Filter _SYSTEMD_UNIT=kubelet.service
          Read_From_Tail On

      [INPUT]
          # Grab EDP namespace logs to separate index for development team
          Name tail
          Tag kube.edp.*
          Path /var/log/containers/*edp*.log
          multiline.parser docker, cri
          Mem_Buf_Limit 5MB
          Skip_Long_Lines On

    filters: |
      [FILTER]
          Name kubernetes
          Match kube.*
          Merge_Log On
          Keep_Log Off
          K8S-Logging.Parser On
          K8S-Logging.Exclude On

      # START of EDP logs chain
      [FILTER]
          Name kubernetes
          Match kube.edp.*
          Merge_Log On
          Keep_Log Off
          Kube_Tag_Prefix  kube.edp.var.log.containers.
          K8S-Logging.Parser On
          K8S-Logging.Exclude On

    outputs: |
      [OUTPUT]
          Name            es
          Match           kube.*
          Host            opensearch-cluster-master
          Port            9200
          HTTP_User       ${ES_SUPERUSER_USER}
          HTTP_Passwd     ${ES_SUPERUSER_PASSWORD}
          Logstash_Format On
          Logstash_Prefix logstash-infra
          Time_Key        @timestamp
          Replace_Dots    On
          Retry_Limit     False
          Trace_Error     Off
          Suppress_Type_Name On
          tls             On
          tls.verify      Off

      [OUTPUT]
          Name            es
          Match           host.*
          Host            opensearch-cluster-master
          Port            9200
          HTTP_User       ${ES_SUPERUSER_USER}
          HTTP_Passwd     ${ES_SUPERUSER_PASSWORD}
          Logstash_Format On
          Logstash_Prefix logstash-host
          Time_Key        @timestamp
          Replace_Dots    On
          Retry_Limit     False
          Trace_Error     Off
          Suppress_Type_Name On
          tls             On
          tls.verify      Off

      [OUTPUT]
          Name            es
          Match           kube.edp.*
          Host            opensearch-cluster-master
          Port            9200
          HTTP_User       ${ES_SUPERUSER_USER}
          HTTP_Passwd     ${ES_SUPERUSER_PASSWORD}
          Logstash_Format On
          Logstash_Prefix logstash-edp
          Time_Key        @timestamp
          Replace_Dots    On
          Retry_Limit     False
          Trace_Error     Off
          Suppress_Type_Name On
          tls             On
          tls.verify      Off
