Skip to content

feat: add keyless OpenCode Google MCP identity - #1

Merged
xnoto merged 3 commits into
mainfrom
feat/opencode-managed-mcp-identity
Aug 27, 2026
Merged

feat: add keyless OpenCode Google MCP identity#1
xnoto merged 3 commits into
mainfrom
feat/opencode-managed-mcp-identity

Conversation

@xnoto

@xnoto xnoto commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add the dedicated keyless opencode-mcp service account
  • grant the managed Google Cloud MCP tool permission and narrowly scoped discovery roles
  • enable Cloud CLI Execution and bind only system:serviceaccount:opencode:opencode-mcp through Workload Identity Federation

Security

  • no service-account key or secret payload access
  • no Cloud Storage role is granted, keeping the OpenTofu state bucket outside the identity's access boundary

Blocked deployment prerequisite

This is intentionally a draft until the k3s ServiceAccount OIDC issuer and public discovery/JWKS endpoints are deployed. OpenCode also needs a supported WIF token-refresh integration before the direct Google MCP endpoint can be enabled.

Validation

  • not run locally; GitHub Actions OpenTofu CI is authoritative

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

OpenTofu CI passed

Validation passed. View the workflow run.

@github-actions

Copy link
Copy Markdown

OpenTofu Plan

OpenTofu will perform the following actions:

�[1m  # google_iam_workload_identity_pool.kubernetes�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_iam_workload_identity_pool" "kubernetes" {
      �[32m+�[0m�[0m deletion_policy           = "DELETE"
      �[32m+�[0m�[0m description               = "k3s ServiceAccount identities for Make IT Work Cloud workloads."
      �[32m+�[0m�[0m display_name              = "k3s workloads"
      �[32m+�[0m�[0m id                        = (known after apply)
      �[32m+�[0m�[0m mode                      = (known after apply)
      �[32m+�[0m�[0m name                      = (known after apply)
      �[32m+�[0m�[0m project                   = "makeitworkcloud"
      �[32m+�[0m�[0m state                     = (known after apply)
      �[32m+�[0m�[0m workload_identity_pool_id = "kubernetes"
    }

�[1m  # google_iam_workload_identity_pool_provider.opencode_kubernetes�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_iam_workload_identity_pool_provider" "opencode_kubernetes" {
      �[32m+�[0m�[0m attribute_condition                = "assertion.sub == \"system:serviceaccount:opencode:opencode-mcp\""
      �[32m+�[0m�[0m attribute_mapping                  = {
          �[32m+�[0m�[0m "google.subject" = "assertion.sub"
        }
      �[32m+�[0m�[0m deletion_policy                    = "DELETE"
      �[32m+�[0m�[0m display_name                       = "OpenCode k3s workload"
      �[32m+�[0m�[0m id                                 = (known after apply)
      �[32m+�[0m�[0m name                               = (known after apply)
      �[32m+�[0m�[0m project                            = "makeitworkcloud"
      �[32m+�[0m�[0m state                              = (known after apply)
      �[32m+�[0m�[0m workload_identity_pool_id          = "kubernetes"
      �[32m+�[0m�[0m workload_identity_pool_provider_id = "opencode"

      �[32m+�[0m�[0m oidc {
          �[32m+�[0m�[0m issuer_uri = "https://api.makeitwork.cloud"
        }
    }

�[1m  # google_project_iam_member.opencode_mcp["roles/browser"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_iam_member" "opencode_mcp" {
      �[32m+�[0m�[0m etag    = (known after apply)
      �[32m+�[0m�[0m id      = (known after apply)
      �[32m+�[0m�[0m member  = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m project = "makeitworkcloud"
      �[32m+�[0m�[0m role    = "roles/browser"
    }

�[1m  # google_project_iam_member.opencode_mcp["roles/cloudkms.viewer"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_iam_member" "opencode_mcp" {
      �[32m+�[0m�[0m etag    = (known after apply)
      �[32m+�[0m�[0m id      = (known after apply)
      �[32m+�[0m�[0m member  = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m project = "makeitworkcloud"
      �[32m+�[0m�[0m role    = "roles/cloudkms.viewer"
    }

�[1m  # google_project_iam_member.opencode_mcp["roles/iam.securityReviewer"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_iam_member" "opencode_mcp" {
      �[32m+�[0m�[0m etag    = (known after apply)
      �[32m+�[0m�[0m id      = (known after apply)
      �[32m+�[0m�[0m member  = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m project = "makeitworkcloud"
      �[32m+�[0m�[0m role    = "roles/iam.securityReviewer"
    }

�[1m  # google_project_iam_member.opencode_mcp["roles/mcp.toolUser"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_iam_member" "opencode_mcp" {
      �[32m+�[0m�[0m etag    = (known after apply)
      �[32m+�[0m�[0m id      = (known after apply)
      �[32m+�[0m�[0m member  = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m project = "makeitworkcloud"
      �[32m+�[0m�[0m role    = "roles/mcp.toolUser"
    }

�[1m  # google_project_iam_member.opencode_mcp["roles/serviceusage.serviceUsageViewer"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_iam_member" "opencode_mcp" {
      �[32m+�[0m�[0m etag    = (known after apply)
      �[32m+�[0m�[0m id      = (known after apply)
      �[32m+�[0m�[0m member  = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m project = "makeitworkcloud"
      �[32m+�[0m�[0m role    = "roles/serviceusage.serviceUsageViewer"
    }

�[1m  # google_project_service.this["cloudcli.googleapis.com"]�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_project_service" "this" {
      �[32m+�[0m�[0m deletion_policy    = "DELETE"
      �[32m+�[0m�[0m disable_on_destroy = false
      �[32m+�[0m�[0m id                 = (known after apply)
      �[32m+�[0m�[0m project            = "makeitworkcloud"
      �[32m+�[0m�[0m service            = "cloudcli.googleapis.com"
    }

�[1m  # google_service_account.opencode_mcp�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_service_account" "opencode_mcp" {
      �[32m+�[0m�[0m account_id      = "opencode-mcp"
      �[32m+�[0m�[0m deletion_policy = "DELETE"
      �[32m+�[0m�[0m disabled        = false
      �[32m+�[0m�[0m display_name    = "OpenCode managed MCP"
      �[32m+�[0m�[0m email           = "opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m id              = (known after apply)
      �[32m+�[0m�[0m member          = "serviceAccount:opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
      �[32m+�[0m�[0m name            = (known after apply)
      �[32m+�[0m�[0m project         = "makeitworkcloud"
      �[32m+�[0m�[0m unique_id       = (known after apply)
    }

�[1m  # google_service_account_iam_member.opencode_mcp_workload_identity_user�[0m will be created
�[0m  �[32m+�[0m�[0m resource "google_service_account_iam_member" "opencode_mcp_workload_identity_user" {
      �[32m+�[0m�[0m etag               = (known after apply)
      �[32m+�[0m�[0m id                 = (known after apply)
      �[32m+�[0m�[0m member             = (known after apply)
      �[32m+�[0m�[0m role               = "roles/iam.workloadIdentityUser"
      �[32m+�[0m�[0m service_account_id = (known after apply)
    }

�[1mPlan:�[0m 10 to add, 0 to change, 0 to destroy.
�[0m
Changes to Outputs:
  �[32m+�[0m�[0m opencode_mcp_service_account_email      = "opencode-mcp@makeitworkcloud.iam.gserviceaccount.com"
  �[32m+�[0m�[0m opencode_mcp_workload_identity_provider = (known after apply)
�[90m
─────────────────────────────────────────────────────────────────────────────�[0m

Note: You didn't use the -out option to save this plan, so OpenTofu can't
guarantee to take exactly these actions if you run "tofu apply" now.

@xnoto
xnoto marked this pull request as ready for review August 27, 2026 21:18
@xnoto
xnoto merged commit b99663c into main Aug 27, 2026
3 checks passed
@xnoto
xnoto deleted the feat/opencode-managed-mcp-identity branch August 27, 2026 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant