Status

Current state[One of "Under Discussion", "Accepted", "Rejected"]

Discussion thread: 

JIRA or Github Issue: 

Released: <Doris Version>

Google Doc: <If the design in question is unclear or needs to be discussed and reviewed, a Google Doc can be used first to facilitate comments from others.>

Motivation

Currently, some http interfaces provided by doris are not authenticated (account password check and global/ database/ table permission check are not performed). These interfaces have security problems and need to be authenticated.

In addition, http data is transmitted in plaintext, which is subject to eavesdropping, tampering, and impersonation risks. https is a secure SSL encryption transmission protocol. The doris interface supports https, which greatly improves its security and provides enterprise-level security support.

Related Research

Detailed Design

1. FE Interface Authentication And Https Implementation

Organize Http Documents

Add missing documents and tidy them up.

Http Interface Authentication

For unauthenticated http interfaces, execute CheckPassword and CheckGlobalAuth or CheckDbAuth or CheckTblAuth;

For partially authenticated http interfaces, only CheckPassword is executed, but CheckGlobalAuth or CheckDbAuth or CheckTblAuth is not executed.

Execute CheckGlobalAuth or CheckDbAuth or CheckTblAuth based on the permissions required by the interface, as shown in follow table:

接口名称

功能描述

RequestMapping

是否鉴权

MetaService

fe 元数据相关API,除`/dump` 以外,都为fe 节点之间内部通讯用,/dump 用于获取image 文件的存储路径

  1. GET /image (/info) (/version) (/put) (/journal_id) (/role) (/check)

  2. GET /dump

否(checkFromValidFe)1
(executeCheckPassword )2

GetSmallFileAction

下载在文件管理器中的文件

GET /api/get_small_file?token=xxx&file_id=xxx

(executeCheckPassword + checkGlobalAuth-PrivPredicate.ADMIN)

HealthAction

返回集群当前存活与宕机的be 节点数

GET /api/health

(executeCheckPassword

MetaInfoAction

获取集群内的元数据信息
数据库列表
表列表
表结构

  1. GET /api/meta/namespaces/<ns>/databases

  2. GET /api/meta/namespaces/<ns>/databases/<db>/tables

  3. GET /api/meta/namespaces/<ns>/databases/<db>/tables/<tbl_name>/schema

是(checkWithCookie)
checkGlobalAuth-PrivPredicate.ADMIN

ShowAction

获取集群/数据库的相关信息
元数据信息
PROC 信息
JVM 的Runtime 信息
集群/数据库的数据量

  1. GET /api/show_meta_info?action=xxx

  2. GET /api/show_proc

  3. GET /api/show_runtime_info

  4. GET /api/show_data/<db>

(executeCheckPassword + checkGlobalAuth-PrivPredicate.ADMIN)1,3,4
是(executeCheckPassword + checkGlobalAuth-PrivPredicate.ADMIN)2

StmtExecutionAction

  1. 执行sql 语句并返回结果

  2. 获取sql 中相关表的建表语句

  1. POST /api/query/<ns>/<db>

  2. POST /api/query_schema/<ns>/<db>

是(checkWithCookie)
checkDbAuth-PrivPredicate.ADMIN 1

MetricsAction

获取metrics

GET /metrics

(executeCheckPassword)

BootstrapFinishAction

判断fe 是否启动完成

GET /api/bootstrap

(executeCheckPassword)

ExtraBasepathAction

返回接口API 的base path

GET /api/basepath

(executeCheckPassword)

ImportAction

查看格式为CSV 或PARQUET 的文件内容

POST /api/import/file_review

(executeCheckPassword

StatisticAction

获取集群统计信息、库表数量等

GET /rest/v2/api/cluster_overview

(executeCheckPassword)

BackendsAction

返回be 列表,包括IP、PORT 等信息

GET /api/backends

是(executeCheckPassword)

NOTE:

1. The enable_all_http_auth parameter is added to the fe configuration file. The default value is false, indicating that only the interfaces that have been authenticated before are authenticated. If it is set true, all interfaces (including the newly added interface authentication) are authenticated.

2. For BackendsAction, as required, the interface should require user have GlobalAuth-PrivPredicate.ADMIN permission. However, a user who uses spark-doris-connector/  flink-doris-connector does not have PrivPredicate.ADMIN permission, to ensure that the connector works properly, do not verify the permission of the interface.

3. For MetricsAction, account password is authenticated. You need to configure the account and password when you use Prometheus to collect monitoring items.

Https Implementation

We implement https based on spring boot, and implement https through configuration and http coding.

Currently doris uses many ports, so http and https are not supported at the same time. We could choose http or https by setting "ssl_enable" in fe.conf.

  1. Generate an SSL Certificate
    1. Test environment certificate is generated using keytool or openssl, and production environment certificate is purchased from the CA.
  2. Configure https in Spring Boot
    1. Add ssl certificate configuration items in the fe configuration file, including the port number, certificate path, password, format, alias, and enable or disable (ssl is disabled by default).

      http_port
      https_port = 8040
      ssl_key_store_path
      ssl_key_store_password
      ssl_key_store_type
      ssl_key_store_alias
      ssl_enable
    2. When fe is started, related configuration parameters are read into the HttpServer class, and then ssl parameters are configured using SpringApplicationBuilder().properties(properties).

      server.port = https_port // https端口
      server.http.port = http_port // http端口
      server.ssl.key-store = ssl_key_store_path // 证书路径
      server.ssl.key-store-password = ssl_key_store_password // 证书密码
      server.ssl.key-store-type = ssl_key_store_type // 密钥库类型
      server.ssl.keyalias: ssl_key_store_alias // 证书别名
      server.ssl.enabled = ssl_enable // 是否开启ssl
  3. Implement http connector and redirect http requests to https
    1. Construct the httpConnector and set the http port and https port.
    2. Through TomcatServletWebServerFactory::addAdditionalTomcatConnectors() to add multiple surveillance connection.

2.BE Interface Authentication And Https Implementation

Http Interface Authentication

  1. Without metadata information stored in BE, it is necessary to perform an interactive authentication with FE, which is implemented through RPC calls as follows:

    THttpAuthRequest {

        1: optional string cluster
        2: required string user
        3: required string passwd
        4: optional string user_ip
        5: optional string glb
        6: optional string db
        7: optional string tbl
        8: optional string col
        9: optional string res
        10: optional TPrivilegeType priv_type
        11: optional i64 thrift_rpc_timeout_ms

    }


    THttpAuthResult {

         1. reuired Status.TStatus status

    }

  2. Each Interface requires different permissions, as follows:

    handler

    interface

    whether performs authentication

    permissions required

    JeprofileActions

    get

    /jeheap/dump

    no

    none

    HeapAction

    get

    /pprof/heap

    GrowthAction

    get

    /pprof/growth

    ProfileAction

    get

    /pprof/profile

    PmuProfileAction

    get

    /pprof/pmuprofile

    ContentionAction

    get

    /pprof/contention

    CmdlineAction

    get

    /pprof/cmdline

    SymbolAction

    get

    /pprof/symbol

    head

    /pprof/symbol

    put

    /pprof/symbol

    StreamLoadAction

    put

    /api/{db}/{table}/_load

    yes

    LOAD

    put

    /api/{db}/{table}/_stream_load

    yes

    LOAD

    StreamLoad2PCAction

    put

    /api/{db}/_stream_load_2pc

    yes

    LOAD

    put

    /api/{db}/{table}/_stream_load_2pc

    yes

    LOAD

    DownloadAction

    head

    /api/_download_load

    yes

    USAGE

    head

    /api/_tablet/_download

    head

    /api/_load_error_log

    get

    /api/_download_load

    get

    /api/_tablet/_download

    get

    /api/_load_error_log

    VersionAction

    get

    /api/be_version_info

    yes

    NODE

    HealthAction

    get

    /api/health

    yes

    none

    TabletsInfoAction

    get

    /tablets_json

    yes

    NODE

    TabletsDistributionAction

    get

    /api/tablets_distribution

    yes

    NODE

    TabletMigrationAction

    get

    /api/tablet_migration

    yes

    NODE

    MetricsAction

    get

    /metrics

    no

    none

    MetaAction

    get

    /api/meta/header/{tablet_id}

    yes

    NODE

    ChecksumAction

    get

    /api/checksum

    yes

    NODE

    ReloadTabletAction

    get

    /api/reload_tablet

    yes

    NODE

    post

    /api/restore_tablet

    yes

    NODE

    SnapshotAction

    get

    /api/snapshot

    yes

    NODE

    CompactionAction

    get

    /api/compaction/show

    yes

    NODE

    get

    /api/compaction/run_status

    yes

    NODE

    post

    /api/compaction/run

    yes

    NODE

    ConfigAction

    get

    /api/show_config

    yes

    NODE

    post

    /api/update_config

    yes

    NODE

    CheckRPCChannelAction

    get

    /api/check_rpc_channel/{ip}/{port}/{payload_size}

    yes

    NODE

    ResetRPCChannelAction

    get

    /api/reset_rpc_channel/{endpoints}

    yes

    NODE

    CheckTabletSegmentAction

    post

    /api/check_tablet_segment_lost

    yes

    NODE

    PadRowsetAction

    post

    /api/pad_rowset

    yes

    NODE

Https Implementation

  1. Generate an SSL Certificate

    In developmet environment, SSL certificates can be generated by openssl as follow:

    openssl genrsa -out private.pem 1024

    openssl req -new -x509 -days 3650 -key private.pem -out cert.pem -subj "/CN=my.host.name"

    In production environment, SSL certificates need to be purchased from the CA.

  2. Configure path of SSL Certificate in be.conf

    enable_https = true; 
    ssl_certificate_path = DORIS_HOME_DIR + "/conf/ssl/cert.pem";
    ssl_private_key_path = DORIS_HOME_DIR + "/conf/ssl/private.pem";

  3. Turn on SSL in brpc server

    Fill the sslOption with the path of certificate and private key before starting server.

    if (config::enable_https) {
    auto sslOptions = options.mutable_ssl_options();
      sslOptions->default_cert.certificate = config::ssl_certificate_path;
      sslOptions->default_cert.private_key = config::ssl_private_key_path;
    }
    _server->Start(port, &options);
  4. Redirect http request to HTTPS

    In the brpc server, SSL-only mode can only be implemented using Controller::is_ssl() in callback of each service.

    if (config::ssl_only && !cntl->is_ssl())  {
        cntl->http_response().set_status_code(baidu::rpc::HTTP_STATUS_FOUND);
        cntl->http_response().SetHeader("Location", "https://xxx");
    }

    A global configure for SSL-only mode may be better than the implementation described above, which would be supported by brpc in the future.


Scheduling

I will implement http interface authentication and https implementation of be and fe in turn, maybe it will take about 2 months to finish this feature:

  1. Collate all http interfaces, including interface names, function descriptions, request mapping and authentication.
  2. Add authentication for an interface that is not authenticated.
  3. Implement https interface and provide enterprise-level security support

Reference

https://clickhouse.com/docs/zh/interfaces/http

https://docs.altinity.com/operationsguide/security/clickhouse-hardening-guide/network-hardening/#enable-tls

https://github.com/OKaluzny/springboot-rest-api-angularjs-https

https://github.com/apache/brpc/blob/master/docs/en/server.md#turn-on-ssl

  • No labels