私有存储库身份验证

为了让 Antora 访问私有存储库,您必须为 playbook 中使用的任何私有存储库 URL 提供身份验证凭据。这些凭据可以外部化,这样就不必将它们硬编码到 playbook 中。本页面涵盖了您可以将凭据传递给 Antora 的各种方式,包括内置的 git 凭据存储、自定义凭据存储,甚至您自己的凭据管理器。

让我们首先看一下 Antora 默认接受的身份验证凭据类型,然后再看如何设置并使用它们。

凭据类型

Antora 可以使用 HTTP 基本身份验证与私有存储库进行身份验证。HTTP 基本身份验证需要向服务器发送凭据(通过 HTTPS)以验证您的身份。身份验证凭据包括用户名/密码对或访问(OAuth 2.0)令牌。

用户名/密码对通常是您用于登录托管存储库的服务(GitHub、GitLab 等)的凭据。如果用户名或密码包含在 URL 中具有特殊含义的字符,例如 /#:,则这些字符必须进行 URL 编码(即百分号编码),以免被 URL 解析器误解。请记住,虽然一些 git 主机支持这种身份验证方式,但其他主机不支持。您可能更容易使用访问令牌。

当您的帐户启用了双因素身份验证(2FA)时,您无法使用用户名/密码对对私有存储库进行身份验证。当您尝试时,您将收到错误 401 HTTP Basic: Access Denied

无论出于何种原因,如果 git 主机不允许您使用用户名/密码对进行身份验证,您将需要使用访问令牌。

有两种类型的访问令牌:个人访问令牌和部署令牌。

  • 一个 个人访问令牌 绑定到用户,并授予对您的帐户可以访问的任何私有存储库的访问权限(取决于令牌本身的范围设置)。

  • 一个 部署令牌(不是部署密钥)绑定到项目(即存储库),并授予对单个存储库的访问权限(取决于令牌本身的范围设置)。

由于部署密钥需要使用 SSH 身份验证,而 Antora 中的 git 客户端不支持,因此无法将部署密钥用于 Antora。

通常在您自己的计算机上使用一个个人访问令牌,而在 CI 服务器上使用一个或多个部署令牌。

要为 GitHub 创建访问令牌,请参阅 为命令行创建个人访问令牌。GitHub 目前不支持部署令牌。要为 GitLab 创建访问令牌,请参阅 个人访问令牌部署令牌。对于 Bitbucket,您需要创建一个具有对存储库的读取访问权限的 应用密码

接下来,让我们看看如何通过默认的 git 凭据存储将这些凭据提供给 Antora 的内置凭据管理器。

使用默认的git凭据存储库提供凭据

默认情况下,Antora内置的凭据管理器会自动在git凭据存储库(一个数据库文件)中检查凭据。git凭据存储库的默认路径是$HOME/.git-credentials,如果第一个位置不存在,则为$XDG_CONFIG_HOME/git/credentials

由于Antora在git主机请求凭据时(即按需)会自动查询凭据管理器,因此您不必直接在playbook中指定凭据。实际上,在playbook中的私有内容源看起来与公共内容源一样。以下是playbook中私有内容源的示例:

content:
  sources:
  - url: https://hostname/your-org/private-repository

当Antora收到git主机通知需要身份验证的URL时,它将在凭据存储库中查找匹配的条目。Antora使用URL作为键来查找匹配项。如果在凭据存储库中找到协议(例如https)和主机名(以及可选的存储库路径),则这些凭据将返回给Antora的凭据管理器,并传递给git服务器。

凭据存储库包含零个或多个基于行的条目。如果需要为单个主机名指定多个凭据(例如多个部署令牌),请将每个条目放在单独的行上。每个条目的结构如下:

https://<凭据>@<主机名>

<凭据>可以是用户名/密码对(username:password)或访问令牌(token:)。<主机名>是git服务器的地址(例如github.com)。

如果用户名或密码包含在URL中具有特殊含义的字符,例如/#:,则这些字符必须进行URL编码。(@在用户名或密码中没有特殊含义)。通常情况下,始终对URL中的用户名和密码组件进行URL编码是安全的。此要求仅适用于在git凭据存储库中定义的URL。

要对组件进行URL编码,请在浏览器中打开JavaScript控制台,并运行encodeURIComponent('<组件>'),其中<组件>是用户名或密码值。如果不同,请使用打印的结果代替您的用户名或密码。例如,my#password的URL编码版本是my%23password

您可以通过系统git命令进行交互式地填充凭据存储库,也可以直接编辑凭据存储库。让我们从交互式方法开始。

交互式地填充凭据存储库

您可以使用git命令交互式地填充凭据存储库。这种方法特别有用,因为它允许您验证git服务器是否接受您的凭据。

首先,选择要与Antora一起使用的私有存储库的URL。然后,在您的终端中,为您需要从Antora访问的每个私有存储库运行以下命令:

$ git config --global credential.helper store && \
  echo -n 'Repository URL: ' && read REPLY && \
  git ls-remote -h $REPLY > /dev/null

此命令执行以下步骤:

  1. 全局启用(临时)git凭据存储库。

  2. 提示您输入私有存储库的URL。

  3. 与私有存储库通信,触发要求输入您的凭据。

    如果没有提示您输入凭据,这意味着您的凭据已经存储。
  4. 将凭据存储在$HOME/.git-credentials中(并分配适当的权限)。

如果此脚本成功,您可以在Antora中使用适用的私有存储库,而无需进一步配置。

恢复您的git配置

上述交互式脚本更改了您的git设置,以便全局启用凭据存储库。如果您在Antora之外不使用凭据存储库,请运行以下命令将其禁用:

$ git config --global --remove-section credential

更改此设置不会影响Antora使用凭据存储库的方式。它只影响您本机git客户端的行为。

如果交互式方法对您不起作用,您可以直接填充凭据存储库。让我们尝试一下。

直接填充凭据存储库

要直接向git凭据存储库添加凭据,请创建文件$HOME/.git-credentials并在编辑器中打开它。将每组唯一的凭据(即用户名/密码对或访问令牌加上主机名和可选的存储库路径)放在单独的行上。如果您使用单个git主机和个人访问令牌,则只需要一个条目。如果您使用多个git主机或多个部署令牌,则需要多个条目。

以下是使用用户名/密码对的示例条目:

https://octocat:ilovegit@github.com

以下是使用令牌的示例(注意令牌后面的尾随:):

https://abcdefg0123456:@github.com

要为给定git主机上的特定存储库使用不同的凭据,您可以将存储库路径(即<repo>)附加到条目中,以使匹配更加严格。(存储库路径中的.git文件扩展名是可选的)。

https://<凭据>@<主机名>/<repo>

以下是特定存储库路径的条目示例:

https://octocat:ilovegit@github.com/octocat/Hello-World

以下是几个流行git主机的示例(您需要用实际值替换粗体占位符):

https://TOKEN:@github.com/org/project-docs
https://oauth2:TOKEN@gitlab.com/org/project-docs.git
https://gitlab+deploy-token-TOKEN_ID:TOKEN@gitlab.com/org/project-docs.git
https://x-oauth-token:TOKEN@bitbucket.org/org/project-docs.git
https://USERNAME:APP_PASSWORD@bitbucket.org/org/project-docs.git
在URL中指定存储库路径是可选的。如果不包含它,该凭据对所有共享相同git主机的URL都将使用。
根据您为内容源使用的URL格式以及是否在playbook中配置了ensure_git_suffix键,您可能需要附加.git文件扩展名。
请注意,令牌根据git主机的不同位置位于URL中的不同位置。有关更多详细信息,请参阅OAuth2格式。如果使用Bitbucket应用密码,请注意您必须包含自己的用户名(使用格式USERNAME:APP_PASSWORD)。

为确保凭据文件受到保护,请立即设置其文件权限,以防止他人读取。

$ chmod 600 $HOME/.git-credentials

指定自定义的git凭据存储路径

您可以指示Antora在不同位置查找文件,而不是使用默认路径中的凭据存储,方法是使用--git-credentials-path CLI选项或GIT_CREDENTIALS_PATH环境变量,两者都在运行时设置git.credentials.path playbook键。

以下是一个示例,使用CLI选项指定相对于playbook文件的路径:

$ antora --git-credentials-path=./.git-credentials antora-playbook.yml

要了解如何使用git.credentials.path playbook键的更多信息,包括如何直接在playbook中设置它,请参阅git.credentials.path键的参考文档。

通过环境变量传递凭据

您可以让Antora直接从名为GIT_CREDENTIALS的环境变量中读取凭据,该环境变量在运行时设置git.credentials.contents playbook键。

以下是演示该概念的示例:

$ export GIT_CREDENTIALS='https://octocat:ilovegit@github.com'
$ antora antora-playbook.yml

您甚至可以将此简化为一行(仅为命令范围内定义环境变量):

$ GIT_CREDENTIALS='https://octocat:ilovegit@github.com' antora antora-playbook.yml

在使用Windows命令提示符时,您需要使用set命令定义环境变量:

C:\> set "GIT_CREDENTIALS=https://octocat:ilovegit@github.com" && antora antora-playbook.yml

这种策略在CI环境中最有用,因为可以保护环境变量。在您自己的机器上生成站点时,这也是向Antora传递凭据的一种快速和非正式的方式。

在使用环境变量时,多个条目可以用逗号或换行符分隔。例如:

$ GIT_CREDENTIALS='https://my-github-token:@github.com,https://oauth2:my-gitlab-token@gitlab.com' antora antora-playbook.yml

导出环境变量可以避免每次运行Antora时都输入它。

要了解如何使用git.credentials.contents playbook键的更多信息,包括如何直接在playbook中设置它,请参阅git.credentials.contents键的参考文档。

将凭据传递给凭据管理器的另一种选项是直接在playbook中列出的URL中对其进行编码。由于此选项不会触发挑战-响应工作流程,Antora会自动假定存储库是私有的。

除非您使用占位符来注入真实凭据(如本节末尾所述),否则不建议使用此策略。

如果服务器要求,Antora将提取在主机名之前的凭据(即username:password@token@)并使用它们代表您执行身份验证。

以下是几个流行的git主机的示例(您应该将粗体中的占位符替换为实际值):

示例1. antora-playbook.yml(片段)
content:
  sources:
  - url: https://TOKEN:@github.com/org/project-docs
  - url: https://oauth2:TOKEN@gitlab.com/org/project-docs.git
  - url: https://gitlab+deploy-token-TOKEN_ID:TOKEN@gitlab.com/org/project-docs.git
  - url: https://x-oauth-token:TOKEN@bitbucket.org/org/project-docs.git
  - url: https://USERNAME:APP_PASSWORD@bitbucket.org/org/project-docs.git
请注意,令牌位于URL中的不同位置,具体取决于git主机。有关更多详细信息,请参阅OAuth2格式。如果使用Bitbucket应用密码,请注意必须包含您自己的用户名(使用格式USERNAME:APP_PASSWORD)。

这种方法的缺点是需要直接将凭据放入playbook文件中。不幸的是,Antora目前尚不支持解析playbook文件中的环境变量。但是,您可以通过使用脚本来替换playbook文件中对环境变量的引用来模拟此行为。

假设您在playbook文件中定义了以下源:

示例2. antora-playbook.yml(片段)
content:
  sources:
  - url: https://$GITHUB_TOKEN:@github.com/org-name/project-docs

如果您使用多个需要相同凭据的私有存储库,可以在git键下一次定义凭据,如下所示:

示例3. antora-playbook.yml(片段)
git:
  credentials:
    contents: https://$GITHUB_TOKEN:@github.com

然后,您可以使用以下脚本来展开对环境变量的引用,这样您可以在调用Antora之前在CI中运行它:

$ sed -i s/\$GITHUB_TOKEN/$GITHUB_TOKEN/ antora-playbook.yml
$ antora antora-playbook.yml

尽管存在这种解决方法,我们仍建议使用前面描述的凭据存储集成。

配置自定义凭据管理器

Antora使用的git客户端isomorphic-git为查找认证凭据提供了一个可插拔的凭据管理器,Antora提供了此插件的默认实现。正如您在之前的章节中看到的,此实现假定Antora可以直接以明文形式访问凭据,可以通过文件或环境变量。如果这种安排不符合您的安全要求,您可以用自己的凭据管理器替换内置的凭据管理器。

要编写自定义凭据管理器,请导出一个实现以下方法的JavaScript对象:

示例4. 自定义git凭据管理器的API
configure ({ config, startDir })
async fill ({ url })
async approved ({ url })
async rejected ({ url, auth })
status ({ url })

查找凭据的方法是fill。它必须返回一个{ username, password }{ token }数据对象。当凭据被服务器批准或拒绝时,将调用approvedrejected方法。

可选的configurestatus方法是Antora特有的,扩展了isomorphic-git中凭据管理器通常提供的功能。如果定义了configure方法,Antora每次启动时都会调用它,提供执行初始化步骤的机会,比如定义属性。如果有status方法,则Antora将使用它来查找给定URL是否请求了身份验证。

要激活您的自定义凭据管理器,首先在一个专用的JavaScript文件中编写您的实现,并将其配置为默认导出:

示例5. custom-git-credential-manager.js
module.exports = {
  async fill ({ url }) { ... },
  async approved ({ url }) { ... },
  async rejected ({ url, auth }) { ... },
}

然后按以下方式将凭据管理器注册到playbook中:

git:
  plugins:
    credential_manager: ./custom-git-credential-manager.js

或者,您可以配置插件进行自注册:

示例6. custom-git-credential-manager.js
'use strict'

const git = require('isomorphic-git')

if (!git.cores) git.cores = new Map()
git.cores.set('antora', new Map().set('credentialManager', {
  async fill ({ url }) { ... },
  async approved ({ url }) { ... },
  async rejected ({ url, auth }) { ... },
}))

请注意,在这种情况下,插件名称为credentialManager而不是credential_manager。这是因为playbook构建器会自动为我们驼峰化键名,这是git客户端期望的键名。

当使用自注册凭据管理器时,您可以使用-r选项将其传递给Antora,而不是在playbook中注册:

$ antora -r ./custom-git-credential-manager.js antora-playbook.yml

如果您使用npm全局安装了Antora,可能会遇到问题,无法使您的自注册凭据管理器正常工作。您可能会遇到错误Cannot find module 'isomorphic-git',或者您的自定义凭据管理器不会被调用。要解决此问题,请设置NODE_PATH环境变量,告诉Node.js在哪里查找Antora的依赖项:

$ NODE_PATH=$(npm -g list --parseable=true @antora/site-generator)/node_modules \
  antora -r ./custom-git-credential-manager.js antora-playbook.yml

另一种解决方案是在本地安装Antora(即将Antora包添加到package.json文件的依赖项中,并运行npm i)。

由于自注册插件更为复杂,我们将继续使用在playbook中注册插件的示例。

从git获取凭据

Git提供了一个名为git credential的命令,它作为一个简单的接口,以与git本身相同的方式存储和检索凭据,也可以提示用户输入用户名和密码。我们可以在自定义凭据管理器中使用此命令,允许Antora委托给git查找凭据(从而与用户自己的git设置集成)。

让我们首先创建一个辅助函数,通过git credentials fill与系统git进行交互,以检索URL的凭据:

示例7. system-git-credential-manager.js
'use strict'

const { spawn } = require('child_process')

function callGitCredentialFill (url) {
  const { protocol, host } = new URL(url)
  return new Promise((resolve, reject) => {
    const output = []
    const process = spawn('git', ['credential', 'fill'])
    process.on('close', (code) => {
      if (code) return reject(code)
      const { username, password } = output.join('\n').split('\n').reduce((acc, line) => {
        if (line.startsWith('username') || line.startsWith('password')) {
          const [key, val] = line.split('=')
          acc[key] = val
        }
        return acc
      }, {})
      resolve(password ? { username, password } : username ? { token: username } : undefined)
    })
    process.stdout.on('data', (data) => output.push(data.toString().trim()))
    process.stdin.write(`protocol=${protocol.slice(0, -1)}\nhost=${host}\n\n`)
  })
}

接下来,让我们创建一个凭据管理器,使用此函数填充URL的凭据:

// ...

module.exports = {
  configure () {
    this.urls = {}
  },
  async fill ({ url }) {
    this.urls[url] = 'requested'
    return callGitCredentialFill(url)
  },
  async approved ({ url }) {
    this.urls[url] = 'approved'
  },
  async rejected ({ url, auth }) {
    this.urls[url] = 'rejected'
    const data = { statusCode: 401, statusMessage: 'HTTP Basic: Access Denied' }
    const err = new Error(`HTTP Error: ${data.statusCode} ${data.statusMessage}`)
    err.name = err.code = 'HttpError'
    err.data = data
    if (auth) err.rejected = true
    throw err
  },
  status ({ url }) {
    return this.urls[url]
  },
}

最后,我们需要在playbook中注册凭据管理器:

git:
  plugins:
    credential_manager: ./system-git-credential-manager.js

现在Antora将委托给系统git填充URL的凭据:

$ antora antora-playbook.yml

读者可以根据服务器批准或拒绝凭据的情况存储或删除凭据(提示:使用approvedrejected方法再次调用git credential)。

SSH认证

自2.0版本起,Antora不再支持通过SSH代理进行公钥/私钥身份验证。相反,Antora会将playbook中的git SSH URL透明转换为HTTPS URL,并使用凭据管理器进行身份验证。这意味着您可以在playbook文件中交替使用SSH URL和HTTPS URL,但最终git客户端将通过HTTPS通信。如果由于某种原因,此自动转换不起作用,您需要更新playbook文件以使用正确的HTTPS URL。