- 网络安全
- 认证鉴权
- 运维
- 后端
【免费下载链接】teleport
The easiest, and most secure way to access and protect all of your infrastructure.
Teleport Terraform Provider 是 Teleport 官方提供的基础设施即代码(IaC)方案,它让 Terraform 用户可以通过声明式的.tf文件创建、更新、导入和删除 Teleport 中的动态资源(用户、角色、访问列表、数据库、Kubernetes 集群、加入令牌等)。本文以仓库中 integrations/terraform/README.md 为骨架,结合 provider 源码、构建脚本 与测试套件,完整讲解环境准备、插件编译安装、测试运行、Schema 再生成、本地示例演练以及 Provider 内部架构,读完你可以独立完成 Provider 的开发环境搭建、本地端到端验证与二次开发。
Terraform Provider 在 Teleport 中的定位
Teleport 允许管理员通过动态资源(dynamic resources)管理集群配置,而 Terraform Provider 正是这套机制的 IaC 前端:它在 Terraform 与 Teleport Auth/Proxy 服务之间建立一条经过认证的通道,把teleport_*资源转换为 Teleport API 调用。从 provider/provider.go 的资源注册表可以看到,当前 Provider 同时提供资源(resource)与数据源(data source)两类入口,例如teleport_user、teleport_role、teleport_app、teleport_database、teleport_kube_cluster、teleport_provision_token、teleport_access_list、teleport_lock、teleport_login_rule等,数据源用于从 Teleport 读取信息,资源用于在 Teleport 中创建与维护对象。
Provider 要求目标集群版本不低于15.0.0-0(见 provider.go 中的minServerVersion常量),并在Configure阶段通过client.Ping校验版本兼容性。
开发环境准备
按照 integrations/terraform/README.md 的 Development 一节,搭建开发环境需要两个前置依赖:
- protobuf 编译器:用于从
.proto文件生成 Terraform schema 代码。官方安装指引为grpc.io/docs/protoc-installation/,编译器的存在是make gen-tfschema能够运行的前提。 - Terraform CLI v1.1.0+:Provider 的测试与本地演练都会调用
terraform命令,因此要求本机安装可用的 Terraform。也可以使用版本管理器tfenv安装指定版本;在 Apple M1(arm64)上需要通过环境变量指定架构,例如:TFENV_ARCH=arm64 tfenv install 1.1.6
除此之外,源码编译本身还需要 Go 工具链(与仓库go.mod声明的版本一致)以及make。编译时使用CGO_ENABLED=0静态编译,这一点在 Makefile 中有明确注释:HashiCorp Cloud 不支持运行依赖 CGO 的 Provider,因此产物是纯静态二进制。
构建并安装 Provider 插件
在 integrations/terraform 目录下执行:
make install该目标依赖build与install两个动作。build使用GOWORK=off关闭 workspace 模式、通过 build tagterraformprovider编译出terraform-provider-teleport可执行文件;install则由 install.mk 负责,把它安装到 Terraform 的本地插件目录:
~/.terraform.d/plugins/terraform.releases.teleport.dev/gravitational/teleport/$(VERSION)/$(TERRAFORM_ARCH)/其中VERSION由 install.mk 通过go run ../hack/get-version/get-version.go自动从仓库版本推导,TERRAFORM_ARCH形如linux_amd64、darwin_arm64。这个目录结构是 Terraform 从terraform.releases.teleport.dev/gravitational/teleport源解析 Provider 时必须遵循的布局,因此make install之后,配置了相同source的 Terraform 工程即可直接使用本地构建版本。
运行测试套件
make testmake test会先执行install,然后通过gotestsum运行 testlib 下的全套测试,并把 JUnit 报告写到test-logs/目录。执行前会检查本机是否存在 Terraform v1.4+,不存在时给出提示(Makefile 中的检查逻辑)。
测试以资源为单位组织,例如 user_test.go、role_test.go、provision_token_test.go、access_list_test.go,每个资源的测试都搭配testlib/fixtures/下的.tffixture 文件(如user_0_create.tf、user_1_update.tf等),以"创建 → 更新 → 校验 plan 稳定 → 导入 → 数据源读取 → 删除"的完整生命周期验证资源行为。测试入口分为 OSS 与 Scoped Resources 两种模式(见 terraform_oss_test.go),其中TestTerraformOSSWithCache会以开启缓存(CacheEnabled)的 AuthServer 运行,用于验证 Provider 对 Teleport 端缓存读一致性的适配。
需要聚焦单个用例时,可以通过TEST_ARGS指定:
make test TEST_ARGS='-run TestTerraformOSS/TestApp'Provider 内部架构
架构设计详见 integrations/terraform/ARCHITECTURE.md。Provider 基于 HashiCorp 的 Terraform Plugin Framework 实现,核心思想是把可复用的 Terraform 生命周期机制与资源相关的 Teleport API 调用分离,从而让新增资源只需少量手写代码。主要目标包括:
- 让所有资源的 Terraform 生命周期行为保持一致;
- 复用 integrations/terraform/tfschema 中由代码生成的 schema 与转换函数;
- 隔离 Teleport API 细节与 Terraform Framework 细节;
- 允许传统生成式资源与新的通用驱动(generic driver)资源在迁移期间共存。
代码包布局
provider/provider.go:Provider 入口,负责解析配置、创建认证的 Teleport API 客户端、暴露重试参数,并注册资源与数据源。GetResources/GetDataSources以legacy.ResourceTypes()为底,再插入通用驱动资源,这样被迁移的资源可以覆盖旧注册而不改变对外暴露的 Terraform 资源名。provider/internal/tfdriver:通用资源/数据源驱动,是生命周期机制的实现地,包含ResourceType[T, I]、DataSourceType[T, I]、ResourceClient[T, I](Get/Create/Upsert/Delete)、DataSourceClient[T, I](Get)、ResourceCodec[T]、IdentifierPolicy[T, I]、ResourceNormalizer[T]等类型。provider/internal/resources:资源描述符,把 tfschema 生成的 schema、API 客户端、标识符策略、normalizer 与 revision 提取函数绑定在一起。provider/internal/teleport:把*client.Client适配为tfdriver接口的薄封装层,只关心 Teleport API 调用,不感知 Terraform 的 plan/state/schema。provider/internal/legacy:早于通用驱动的一批生成式资源实现及其注册表。integrations/terraform/tfschema:由protoc-gen-terraform生成的 schema 与拷贝函数,新旧两类资源共用。
驱动层统一的资源生命周期
从 resource.go 可以看到通用驱动把以下行为固化为模板:
- Create 前置检查:创建前先按标识符
Get,若资源已存在于 Teleport 且非单例资源,则报错并提示"要么用tctl rm删除,要么用terraform import导入现有状态"; - Create/Update 前的规范化:调用资源的 Normalizer(例如
CheckAndSetDefaults、ForceKind,实现见 normalize.go),在调用 API 前补齐默认值、强制 kind 等不变量; - 创建后的最终一致性重试:写入后用指数退避轮询
Get,直到资源可读; - 更新后的 revision 收敛:当资源描述符提供
ResourceRevision(一般取metadata.revision)时,Update 会持续轮询直到远端 revision 发生变化,从而保证 Terraform 的写入真正生效(对关闭了 Auth 缓存、读最终一致的部署尤其重要); - Read 的"远端已删除则移除状态":
Get返回 NotFound 时调用resp.State.RemoveResource; - Import 状态解析与填充:通过
IdentifierPolicy.FromImportID解析导入 ID 并回填状态; - 统一的诊断封装:通过
provider/internal/tfdiag输出一致的错误信息。
标识符体系
资源唯一标识符定义在 identifier.go,它决定 Terraform 资源如何映射到 Teleport 集群中的对象,同时决定terraform import时使用的 ID 格式:
NameIdentifier:大多数以metadata.name唯一标识的资源,导入 ID 即资源名;ScopeQualifiedNameIdentifier:以(name, scope)唯一标识的作用域资源,导入 ID 为scope::name;CompositeIdentifier:由两部分标识的资源,导入 ID 形如prefix/name(例如 Access List 的成员 = Access List 名 + 成员名);SingletonIdentifier:固定标识的集群单例资源(如 Auth 偏好、集群网络配置)。
更新 Provider:重新生成 Schema
当 Teleport 的 API 定义(.proto文件)发生变化时,需要重新生成 Terraform schema 与 Provider 代码。在 integrations/terraform 目录执行:
make gen-tfschema该目标会调用protoc,逐个读取 Makefile 中列出的protoc-gen-terraform-*.yaml配置,把../../api/proto下的 proto 文件(例如teleport/legacy/types/types.proto、teleport/accesslist/v1/accesslist.proto、teleport/workloadidentity/v1/resource.proto、teleport/loginrule/v1/loginrule.proto等)转换为tfschema下的*_terraform.go文件,随后用go run ./gen/main.go重新生成 legacy 代码。
每个protoc-gen-terraform-*.yaml都是 schema 生成规则的配置源,以 protoc-gen-terraform-example.yaml 为例,它声明了:
types:要导出为 Terraform 的顶层类型;injected_fields:注入id计算字段(供集成测试使用,Provider 本身不用);exclude_fields:排除的字段(如metadata.id、metadata.namespace、metadata.revision,资源以 name 作为唯一标识);computed_fields/required_fields:标记 Computed 与 Required 的字段;plan_modifiers:例如Metadata.name上挂RequiresReplace(),资源名变更时强制重建;custom_types:时间戳、Duration 等自定义类型映射;validators:例如Metadata.expires必须指向未来时间。
若 schema 发生变化导致公开文档需要同步,还需重新渲染文档:
make docsmake docs的实现见 gen/docs.sh:它在临时目录用terraform providers schema -json导出 Provider schema,调用定制版tfplugindocs渲染 Markdown,再转换为.mdx并复制到 docs/pages/reference/infrastructure-as-code/terraform-provider。渲染模板位于 templates(如 resources.md.tmpl),默认模板会尝试包含examples/resources/teleport_<资源名>/resource.tf示例文件。
本地端到端演练
README 提供了完整的最小闭环演练流程,以下按步骤展开(全部命令在 integrations/terraform 目录下执行)。
1. 启动 Teleport
teleport start本地启动一个 Teleport Auth + Proxy 组合实例,作为 Provider 的接入目标。
2. 创建 Terraform 用户与角色
tctl create example/terraform.yaml tctl auth sign --format=file --user=terraform --out=/tmp/terraform-identity --ttl=10h第一步创建名为terraform的用户及其角色,第二步以tctl auth sign签发出有效期 10 小时的身份文件(identity file)到/tmp/terraform-identity。身份文件是 Provider 推荐的连接凭据形态,它同时支持经 Proxy Service(443/3080 端口)与 Auth Service(3025 端口)连接。
注意:仓库当前示例目录 examples/provider 提供的是 Provider 声明示例(provider.tf 面向自托管、provider-cloud.tf 面向 Teleport Enterprise 托管租户)以及 scoped 场景的角色模板 scoped-provider-role.yaml。README 中提到的
example/terraform.yaml需结合你所用的 Teleport 版本按需准备,其作用等价于为该用户授予管理动态资源的角色权限。
3. 准备main.tf
cp example/main.tf.example example/main.tfREADME 指出:上一步导出的身份文件路径为/tmp/terraform-identity,若你选择了其他位置,需要同步修改main.tf。典型的最小配置形如:
terraform { required_providers { teleport = { source = "terraform.releases.teleport.dev/gravitational/teleport" version = "~> 15.0" } } } provider "teleport" { addr = "proxy.example.com:443" # 或 auth.example.com:3025 identity_file_path = "terraform-identity/identity" }Provider 的可用配置项在 provider.go 的GetSchema中定义,除addr与identity_file_path外还包括:cert_path/cert_base64、key_path/key_base64、root_ca_path/root_ca_base64(TLS 密钥直连 Auth 方式)、profile_name/profile_dir(复用 tsh profile)、identity_file/identity_file_base64、insecure(跳过代理证书校验,不推荐生产使用)、retry_base_duration(默认1s)、retry_cap_duration(默认5s)、retry_max_tries(默认10)、dial_timeout_duration(默认30s),以及原生 MachineID 接入所需的join_method、join_token、audience_tag、gitlab_id_token_env_var、kubernetes_token_path、scoped。每个配置项都可以通过同名环境变量覆盖(例如TELEPORT_ADDR、TELEPORT_IDENTITY_FILE等,常量定义见api/constants包)。addr必须是host:port格式,否则 Provider 会直接报错(validateAddr)。
4. 复制示例资源定义
cp example/user.tf.example example/user.tf cp example/role.tf.example example/role.tf cp example/provision_token.tf.example example/provision_token.tf这些示例资源的字段结构与仓库测试夹具一致,可以参考 testlib/fixtures 下的真实用例,例如 user_0_create.tf:
resource "teleport_user" "test" { version = "v2" metadata = { name = "test" expires = "2035-10-12T07:20:50Z" labels = { example = "yes" } } spec = { roles = ["terraform-provider"] traits = { logins1 = ["example"] logins2 = ["example"] } oidc_identities = [{ connector_id = "oidc" username = "example" }] github_identities = [{ connector_id = "github" username = "example" }] saml_identities = [{ connector_id = "saml" username = "example" }] } }role_0_create.tf 展示了角色资源的最小形态:
resource "teleport_role" "test" { version = "v8" metadata = { name = "test" } spec = { allow = { logins = ["anonymous"] } } }provision_token_0_create.tf 则展示了加入令牌资源:
resource "teleport_provision_token" "test" { version = "v2" metadata = { name = "test" expires = "2038-01-01T00:00:00Z" labels = { example = "yes" } } spec = { roles = ["Node", "Auth"] } }README 特别提醒:部分资源需要前置步骤才能生效(例如 Provision Token 的 IAM 变体、Kubernetes 集群、集成类资源等),首次演练建议从用户、角色这类无外部依赖的资源开始。
5. 应用变更
make applymake apply(见 Makefile)等价于:
terraform -chdir=example init && terraform -chdir=example apply -auto-approveinit会从本地插件目录解析terraform.releases.teleport.dev/gravitational/teleport源,apply -auto-approve免确认执行。若此前执行过make install且main.tf的版本约束与本地一致,Terraform 会直接命中本地构建的插件。
6. 修改并重新应用
make reapply修改任意.tf文件后执行。reapply只执行terraform apply(不重新 init,保留交互确认),Terraform 会计算 plan 并只对变更字段下发Upsert。得益于驱动层基于metadata.revision的收敛轮询(见上文"更新后的 revision 收敛"),apply会一直等到 Teleport 侧真正应用变更后才把新状态写入 state。
7. 清理
make destroy等价于terraform destroy -auto-approve,删除 Terraform 管理的全部资源并清理 state。
如何为 Provider 贡献新资源
新资源开发建议直接使用通用驱动(legacy 生成器已弃用,待存量资源全部迁移后移除),完整流程见 integrations/terraform/CONTRIBUTING.md,要点如下:
- 生成 schema 代码:若 tfschema 中已有所需 schema 则直接复用;否则新增/修改
protoc-gen-terraform-*.yaml、在Makefile的gen-tfschema中补充protoc调用,然后运行make gen-tfschema。 - 编写 API 适配层:在
provider/internal/teleport/<resource>.go中实现tfdriver.ResourceClient[T, I](Get/Create/Upsert/Delete)或DataSourceClient[T, I](Get),该层只做 Teleport API 调用,不感知 Terraform 概念;若更新需要保留服务端自有字段,可实现tfdriver.UpdatePreparer[T]。 - 编写资源描述符:在
provider/internal/resources/<resource>.go中把 API 适配层、schema/转换函数、标识符策略、normalizer(如CheckAndSetDefaults、ForceKind)与ResourceRevision组合成ResourceType[T, I]。标识符策略需按资源特性选择:按名导入用NameIdentifierPolicy,作用域资源用ScopeQualifiedNameIdentifierPolicy,双段 ID 用CompositeIdentifierPolicy,单例用SingletonIdentifierPolicy。 - 注册资源:在 provider.go 的
GetResources/GetDataSources的 generic 映射中加入"teleport_<name>": resources.NewXxxResourceType(),注意资源只允许在一个地方注册(generic 映射或 legacy 注册表)。 - 补充测试与夹具:在
testlib/fixtures/添加<resource>_0_create.tf、<resource>_1_update.tf(必要时加<resource>_data_source.tf),在testlib/<resource>_test.go中覆盖 create/read/update/delete、plan 稳定性、import、data source 与敏感字段不泄漏到 state 等行为。 - 更新文档:涉及公开 surface 变化时运行
make docs。若需要为某资源定制文档,可将 templates/resources.md.tmpl 复制为templates/resources/<resource_name>.md.tmpl,用tffile函数引用示例文件并追加自定义说明。
对于存量 legacy 资源的迁移,CONTRIBUTING.md 强调兼容性优先:先记录现有资源名、schema 路径与 Required/Computed/Sensitive 标记、导入 ID 格式、create/update 方法选择、默认值与强制 kind 行为、secret 字段处理、重试行为等,再迁移注册、保持公开 Terraform 类型名不变,并围绕"旧导入 ID 可导入、旧 fixture 应用不触发意外替换、plan-only 检查"等场景强化测试。RFD 153 类资源还需遵循 rfd/0153-resource-guidelines.md 的资源规范。
结语
Teleport Terraform Provider 通过"生成式 schema + 通用驱动"的双层设计,把 Terraform 生命周期的一致性与 Teleport API 的多样性解耦:日常使用者只需要make install后按 README 的七步走完本地闭环即可上手管理动态资源;开发者则可以从 ARCHITECTURE.md 理解驱动边界,按 CONTRIBUTING.md 的六步流程低门槛地贡献新资源。本文涉及的关键文件都保留在当前仓库中,可继续深入阅读:
- 构建与安装:integrations/terraform/Makefile、integrations/terraform/install.mk
- Provider 入口与配置项:integrations/terraform/provider/provider.go
- 生命周期驱动:integrations/terraform/provider/internal/tfdriver/resource.go
- 标识符体系:integrations/terraform/provider/internal/tfdriver/identifier.go
- Schema 生成配置示例:integrations/terraform/protoc-gen-terraform-example.yaml
- 测试夹具:integrations/terraform/testlib/fixtures
- 文档生成:integrations/terraform/gen/docs.sh 与 integrations/terraform/templates
- 网络安全
- 认证鉴权
- 运维
- 后端
【免费下载链接】teleport
The easiest, and most secure way to access and protect all of your infrastructure.
相关推荐
yajl-objc vs 原生JSON库:为什么它是Objective-C项目的最佳选择?
yajl objc vs 原生JSON库:为什么它是Objective C项目的最佳选择? 在Objective C开发中,JSON处理是日常任务的重要组成部分
IGLDropDownMenu与CocoaPods集成:从安装到部署的完整流程
IGLDropDownMenu与CocoaPods集成:从安装到部署的完整流程 IGLDropDownMenu是一款为iOS应用开发的下拉菜单组件,以其精美的动
移动开发UI库/组件Terraform完整指南:如何用基础设施即代码快速管理云资源
Terraform完整指南:如何用基础设施即代码快速管理云资源 Terraform是一款流行的开源工具,用于构建、变更和版本化云基础架构。作为基础设施即代码(I
IaCCLI基础设施云原生DevOps
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考