feat: tailscale-operator Workload Identity(beta) - infra#7333
feat: tailscale-operator Workload Identity(beta) - infra#7333
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30028b1819
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| depends_on = [ | ||
| tailscale_acl.this, | ||
| aws_s3_object.oidc_discovery, | ||
| aws_s3_object.oidc_jwks, |
There was a problem hiding this comment.
Add public-read policy dependency before WIF creation
tailscale_federated_identity.k8s_operator currently waits for the two S3 objects but not for aws_s3_bucket_policy.k8s_oidc_public_read, so on a fresh apply Terraform can start WIF creation while the issuer documents are still private and Tailscale’s issuer validation gets a 403. This makes applies flaky/failing in the exact bootstrap path this commit introduces; include the bucket policy in depends_on to guarantee the issuer URL is publicly readable before creating the federated identity.
Useful? React with 👍 / 👎.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Plan Result (terraform/tailscale/lolice)
Change Result (Click me) # aws_s3_bucket.k8s_oidc will be created
+ resource "aws_s3_bucket" "k8s_oidc" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "lolice-k8s-oidc"
+ bucket_domain_name = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_region = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = "ap-northeast-1"
+ request_payer = (known after apply)
+ tags_all = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
+ cors_rule (known after apply)
+ grant (known after apply)
+ lifecycle_rule (known after apply)
+ logging (known after apply)
+ object_lock_configuration (known after apply)
+ replication_configuration (known after apply)
+ server_side_encryption_configuration (known after apply)
+ versioning (known after apply)
+ website (known after apply)
}
# aws_s3_bucket_policy.k8s_oidc_public_read will be created
+ resource "aws_s3_bucket_policy" "k8s_oidc_public_read" {
+ bucket = (known after apply)
+ id = (known after apply)
+ policy = (known after apply)
+ region = "ap-northeast-1"
}
# aws_s3_bucket_public_access_block.k8s_oidc will be created
+ resource "aws_s3_bucket_public_access_block" "k8s_oidc" {
+ block_public_acls = true
+ block_public_policy = false
+ bucket = (known after apply)
+ id = (known after apply)
+ ignore_public_acls = true
+ region = "ap-northeast-1"
+ restrict_public_buckets = false
}
# aws_s3_bucket_server_side_encryption_configuration.k8s_oidc will be created
+ resource "aws_s3_bucket_server_side_encryption_configuration" "k8s_oidc" {
+ bucket = (known after apply)
+ id = (known after apply)
+ region = "ap-northeast-1"
+ rule {
+ blocked_encryption_types = []
+ apply_server_side_encryption_by_default {
+ sse_algorithm = "AES256"
# (1 unchanged attribute hidden)
}
}
}
# aws_s3_object.oidc_discovery will be created
+ resource "aws_s3_object" "oidc_discovery" {
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = (known after apply)
+ bucket_key_enabled = (known after apply)
+ checksum_crc32 = (known after apply)
+ checksum_crc32c = (known after apply)
+ checksum_crc64nvme = (known after apply)
+ checksum_sha1 = (known after apply)
+ checksum_sha256 = (known after apply)
+ content = (known after apply)
+ content_type = "application/json"
+ etag = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ key = ".well-known/openid-configuration"
+ kms_key_id = (known after apply)
+ region = "ap-northeast-1"
+ server_side_encryption = (known after apply)
+ storage_class = (known after apply)
+ tags_all = (known after apply)
+ version_id = (known after apply)
}
# aws_s3_object.oidc_jwks will be created
+ resource "aws_s3_object" "oidc_jwks" {
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = (known after apply)
+ bucket_key_enabled = (known after apply)
+ checksum_crc32 = (known after apply)
+ checksum_crc32c = (known after apply)
+ checksum_crc64nvme = (known after apply)
+ checksum_sha1 = (known after apply)
+ checksum_sha256 = (known after apply)
+ content = jsonencode(
{
+ keys = []
}
)
+ content_type = "application/json"
+ etag = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ key = "openid/v1/jwks"
+ kms_key_id = (known after apply)
+ region = "ap-northeast-1"
+ server_side_encryption = (known after apply)
+ storage_class = (known after apply)
+ tags_all = (known after apply)
+ version_id = (known after apply)
}
# aws_ssm_parameter.operator_wif_audience will be created
+ resource "aws_ssm_parameter" "operator_wif_audience" {
+ arn = (known after apply)
+ data_type = (known after apply)
+ description = "Tailscale WIF audience for the Kubernetes Operator (not a secret)"
+ has_value_wo = (known after apply)
+ id = (known after apply)
+ insecure_value = (known after apply)
+ key_id = (known after apply)
+ name = "/lolice/tailscale/operator-wif-audience"
+ region = "ap-northeast-1"
+ tags = {
+ "Project" = "lolice"
+ "Purpose" = "tailscale-k8s-operator-wif"
}
+ tags_all = {
+ "Project" = "lolice"
+ "Purpose" = "tailscale-k8s-operator-wif"
}
+ tier = (known after apply)
+ type = "String"
+ value = (sensitive value)
+ value_wo = (write-only attribute)
+ version = (known after apply)
}
# aws_ssm_parameter.operator_wif_client_id will be created
+ resource "aws_ssm_parameter" "operator_wif_client_id" {
+ arn = (known after apply)
+ data_type = (known after apply)
+ description = "Tailscale WIF client ID for the Kubernetes Operator (not a secret)"
+ has_value_wo = (known after apply)
+ id = (known after apply)
+ insecure_value = (known after apply)
+ key_id = (known after apply)
+ name = "/lolice/tailscale/operator-wif-client-id"
+ region = "ap-northeast-1"
+ tags = {
+ "Project" = "lolice"
+ "Purpose" = "tailscale-k8s-operator-wif"
}
+ tags_all = {
+ "Project" = "lolice"
+ "Purpose" = "tailscale-k8s-operator-wif"
}
+ tier = (known after apply)
+ type = "String"
+ value = (sensitive value)
+ value_wo = (write-only attribute)
+ version = (known after apply)
}
# tailscale_acl.this will be updated in-place
~ resource "tailscale_acl" "this" {
~ acl = jsonencode(
~ {
~ tagOwners = {
+ "tag:k8s" = [
+ "tag:k8s-operator",
]
# (3 unchanged attributes hidden)
}
# (2 unchanged attributes hidden)
}
)
id = "dca925a2-b72b-a210-25af-3ccbdb1f4046"
}
# tailscale_federated_identity.k8s_operator will be created
+ resource "tailscale_federated_identity" "k8s_operator" {
+ audience = (known after apply)
+ created_at = (known after apply)
+ description = "lolice k8s-operator WIF"
+ id = (known after apply)
+ issuer = (known after apply)
+ scopes = [
+ "auth_keys",
+ "devices:core",
+ "services",
]
+ subject = "system:serviceaccount:tailscale-operator:operator"
+ tags = [
+ "tag:k8s-operator",
]
+ updated_at = (known after apply)
+ user_id = (known after apply)
}
Plan: 9 to add, 1 to change, 0 to destroy.
Changes to Outputs:
+ k8s_oidc_issuer_url = (known after apply)
+ k8s_operator_wif_audience = (known after apply)
+ k8s_operator_wif_client_id = (known after apply) |
Ansible Plan ResultsMode: shanghai-1: control-plane
1 changed Changed Tasks (1)
shanghai-1: node-shanghai-1
No changes shanghai-2: control-plane
1 changed Changed Tasks (1)
shanghai-2: node-shanghai-2
No changes shanghai-3: control-plane
1 changed Changed Tasks (1)
shanghai-3: node-shanghai-3
No changes Plan executed on all nodes in parallel. |
See PR commits for changes. Related: boxp/lolice#514