配置 OAuth 身份验证

有关 ODBC OAuth 连接属性的列表,请参阅 ODBC DSN 连接属性

以下过程将:

  1. 配置 Keycloak 18.0。

  2. 创建 OAuth 身份验证记录。

  3. 使用 POST 请求检索访问令牌。

  4. 使用示例应用程序 sample application 向 Vertica 验证身份,并将访问令牌作为实参和令牌刷新参数(可选)传递。

配置 keycloak

以下过程将在 203.0.113.1 上配置 Keycloak 18.0.0 服务器。

使用 TLS(可选)

如果要使用 TLS,您必须获取由受信任的 CA 签名的 Keycloak 证书和密钥。为方便起见,此示例将使用自签名 CA。

  1. 生成 CA 证书:

    => CREATE KEY SSCA_key TYPE 'RSA' LENGTH 2048;
    CREATE KEY
    
    => CREATE CA CERTIFICATE SSCA_cert
    SUBJECT '/C=US/ST=Massachusetts/L=Cambridge/O=Micro Focus/OU=Vertica/C N=Vertica Root CA'
    VALID FOR 3650
    EXTENSIONS 'nsComment' = 'Self-signed root CA cert'
    KEY SSCA_key;
    CREATE CERTIFICATE
    
  2. 生成由您的 CA 签名的服务器密钥和证书,将证书的 subjectAltName 设置为您的 Keycloak 服务器的 DNS 和/或 IP 地址:

    => CREATE KEY keycloak_key TYPE 'RSA' LENGTH 2048;
    CREATE KEY
    
    => CREATE CERTIFICATE keycloak_cert
    SUBJECT '/C=US/ST=Massachussets/L=Cambridge/O=Micro Focus/OU=Vertica/CN=Vertica Server'
    SIGNED BY SSCA_cert
    EXTENSIONS 'nsComment' = 'Keycloak CA', 'extendedKeyUsage' = 'serverAuth', 'subjectAltName' = 'DNS.1:dnsserver,IP:203.0.113.1'
    KEY keycloak_key;
    CREATE CERTIFICATE
    
  3. 使用生成的密钥的 key 列内容创建文件 keycloak_directory/conf/keyfile.pem

    => SELECT key FROM cryptographic_keys WHERE name = 'keycloak_key';
    
  4. 使用生成的证书的 certificate_text 列内容创建文件 keycloak_directory/conf/certfile.pem

    => SELECT certificate_text FROM certificates WHERE name = 'keycloak_cert';
    
  5. 将生成的 CA 证书的 certificate_text 列内容附加到系统的 CA 捆绑包中。默认 CA 捆绑包路径和格式因分发版而异;有关详细信息,请参阅 SystemCABundlePath

    => SELECT certificate_text FROM certificates WHERE name = 'SSCA_cert';
    
  6. 设置 SystemCABundlePath 配置参数:

    => ALTER DATABASE DEFAULT SET SystemCABundlePath = 'path/to/ca_bundle';
    

启动 keycloak

  1. 输入以下命令获取最小配置,以创建 Keycloak 管理员并在 start-dev 模式下启动 Keycloak:

    $ KEYCLOAK_ADMIN=kcadmin
    $ export KEYCLOAK_ADMIN
    $ KEYCLOAK_ADMIN_PASSWORD=password
    $ export KEYCLOAK_ADMIN_PASSWORD
    $ cd keycloak_directory/bin/
    $ ./kc.sh start-dev --hostname 203.0.113.1 --https-certificate-file ../conf/certfile.pem --https-certificate-key-file=../conf/keyfile.pem
    
  2. 使用浏览器打开 Keycloak 控制台(这些示例使用默认端口):

    • 对于 HTTP:http://203.0.113.1:8080

    • 对于 HTTPS:http://203.0.113.1:8443

  3. 以管理员身份登录。

  4. (可选)为了更加方便地测试 OAuth,请导航到领域设置 (Realm Settings) > 令牌 (Tokens),然后将访问令牌生命期 (Access Token Lifespan) 增加到更大的值(默认值为 5 分钟)。

创建 Vertica 客户端

  1. 导航到客户端 (Clients) 并单击创建 (Create)。此时会显示添加客户端 (Add Client) 页面。

  2. 客户端 ID (Client ID) 中,输入 vertica

  3. 单击保存 (Save)。此时会显示客户端配置页面。

  4. 设置 (Settings) 选项卡中,使用访问类型 (Access Type) 下拉菜单选择机密 (confidential)

  5. 凭据 (Credentials) 选项卡中,记下密码 (Secret)。这是用于在令牌过期时刷新令牌的客户端密码。

创建 Keycloak 用户

Keycloak 用户可映射到同名的 Vertica 用户。此示例创建了一个 Keycloak 用户 oauth_user

  1. 用户 (Users) 选项卡中,单击添加用户 (Add user)。此时会显示添加用户 (Add user) 页面。

  2. 用户名 (Username) 中,输入 oauth_user

  3. 凭据 (Credentials) 选项卡中,输入密码。

配置 Vertica

创建身份验证记录

为 OAuth 创建身份验证记录。

以下 身份验证记录v_oauth 使用 OAuth 令牌(而不是用户名和密码)对来自任何 IP 地址的用户进行身份验证,并且使用以下参数。身份提供者是 Keycloak 18.0.0:

  • client_id:机密客户端 vertica 在 Keycloak 中注册。

  • client_secret:客户端密钥,由 Keycloak 生成。

  • discovery_url:也称为 OpenID 提供者配置文档,这是包含有关身份提供者的配置和端点的信息的端点。

=> CREATE AUTHENTICATION v_oauth METHOD 'oauth' HOST '0.0.0.0/0'
=> ALTER AUTHENTICATION v_oauth SET client_id = 'vertica';
=> ALTER AUTHENTICATION v_oauth SET client_secret = 'client_secret';
=> ALTER AUTHENTICATION v_oauth SET discovery_url = 'https://203.0.113.1:8443/realms/myrealm/.well-known/openid-configuration';
=> ALTER AUTHENTICATION v_oauth SET introspect_url = 'https://203.0.113.1:8443/realms/myrealm/protocol/openid-connect/token/introspect';

创建 Vertica 用户

Vertica 用户可映射到用户名相同的 Keycloak 用户。

  1. 要映射到 Keycloak 用户 oauth_user,请创建一个同名的 Vertica 用户。无需指定密码,因为身份验证由身份提供程序执行:

    => CREATE USER oauth_user;
    
  2. 将 OAuth 身份验证记录授予用户(或其角色):

    => GRANT AUTHENTICATION v_oauth TO oauth_user;
    => GRANT ALL ON SCHEMA PUBLIC TO oauth_user;
    

检索访问令牌

获取 OAuth 访问令牌的一种简单方法是将 POST 请求发送到令牌端点,同时提供 Keycloak 用户的凭据。例如,oauth_user

$ curl --location --request POST 'http://203.0.113.1:8080/realms/master/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=oauth_user' \
--data-urlencode 'password=oauth_user_password' \
--data-urlencode 'client_id=vertica' \
--data-urlencode 'client_secret=client_secret' \
--data-urlencode 'grant_type=password'

如果身份验证正确,Keycloak 会以 JSON 的格式作出响应。然后,您可以将返回的访问令牌、刷新令牌和范围与相应的连接属性一起使用。

{
   "access_token":"access_token",
   "expires_in":60,
   "refresh_expires_in":1800,
   "refresh_token":"refresh_token",
   "token_type":"Bearer",
   "not-before-policy":0,
   "session_state":"6745892a-aa74-452f-b6b9-c45637193859",
   "scope":"profile email"
}

运行示例应用程序

在令牌过期之前,OAuth 示例应用程序至少会将访问令牌作为实参来对数据库进行身份验证。如果您希望示例应用程序在令牌过期后刷新令牌,您必须指定以下内容。示例应用程序会将这些内容放入 JSON 字符串:OAuthJsonConfig 或 (ODBC) oauthjsonconfig (JDBC)。

  • 刷新令牌

  • 客户端 ID

  • 客户端密码

  • 令牌 URL

ODBC

  1. 遵循 README 中的说明。

  2. 运行示例应用程序,同时将 OAuth 参数作为实参传递:

    • 在令牌过期之前进行身份验证:

      $ ./a.out --access-token OAuthAccessToken
      
    • 在访问令牌过期后进行身份验证并静默刷新访问令牌:

      $ ./a.out --access-token OAuthAccessToken
          --refresh-token OAuthRefreshToken
          --client-id OAuthClientID
          --client-secret OAuthClientSecret
          --token-url OAuthTokenURL
      

JDBC

  1. 遵循 README 中的说明。

  2. 运行示例应用程序,同时将 OAuth 参数作为实参传递:

    • 在令牌过期之前进行身份验证:

      $ mvn compile exec:java -Dexec.mainClass=OAuthSampleApp -Dexec.args="vertica_host database_name --access-token oauthaccesstoken"
      
    • 在访问令牌过期后进行身份验证并静默刷新访问令牌:

      $ mvn compile exec:java -Dexec.mainClass=OAuthSampleApp -Dexec.args="vertica_host database_name --access-token oauthaccesstoken
          --refresh_token oauthrefreshtoken
          --client-id oauthclientid
          --client-secret oauthclientsecret
          --token-url oauthtokenurl"
      

故障排除

要获取 TLS 的调试信息,请使用 -Djavax.net.debug=ssl 标记。

将 CA 证书导入 Java 信任库

如果您通过 TLS 配置身份提供程序(即,如果您对令牌或刷新 URL 使用 HTTPS 端点),且其证书不是由熟知的 CA 颁发的,则必须使用 keytool 导入颁发机构的 CA 证书。

例如,将证书 keycloak/cert.crt 添加到 Java 信任库:

$ keytool -trustcacerts -keystore /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.261-2.6.22.2.el7_8.x86_64/jre/lib/security/cacerts -storepass changeit -importcert -alias keycloak -file /keycloak/cert.crt