Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure
Before Porter can create a cluster, you need to grant it access to your cloud account. Porter uses secure credential methods that don’t require storing static API keys.
AWS
GCP
Azure
Porter uses AWS IAM role assumption via the AssumeRoleoperation to access your account. You create a role in your AWS account and declare that you trust Porter to assume it. This eliminates static credentials and makes access easy to revoke.
After selecting AWS as your cloud provider, log into your AWS Console and find your 12-digit Account ID in the top-right corner.Enter this ID in Porter and click Grant Permissions.
2
Create the CloudFormation stack
Porter opens the AWS CloudFormation console in a new tab to create a stack that provisions the porter-manager IAM role.
If the popup is blocked, check your browser settings and allow popups from Porter.
Scroll to the bottom of the CloudFormation page, check the I acknowledge that AWS CloudFormation might create IAM resources box, and click Create Stack.Wait for the stack creation to complete (this takes a few minutes).
The IAM role must remain in your AWS account for Porter to manage your infrastructure. Deleting it will prevent Porter from making changes.
First, delete any clusters through the Porter dashboard
Navigate to CloudFormation Stacks in your AWS console
Select the stack named PorterRole and click Delete
This removes the IAM role and prevents Porter from accessing your account.
Porter connects to GCP using Workload Identity Federation. Workload Identity Federation offers a mechanism for Porter to connect with your GCP project without requiring any static keys. Setup runs in Google Cloud Shell with a single command Porter generates for your project.
Your GCP project needs an active billing account attached. Porter cannot provision infrastructure without one.The Google account running the setup must have these project-level roles (or roles/owner, which covers all of them):
In Porter, select GCP. Enter your GCP project ID (visible at the top of any page in the GCP Console) and click Connect. Porter generates a one-time setup command scoped to this integration.
2
Run the setup in Cloud Shell
In the Porter dashboard:
Copy the command shown in the Run Setup in Cloud Shell panel.
Click Open Cloud Shell to launch a new tab with the porter-dev/gcp-onboarding repository pre-loaded.
Cloud Shell will warn that the repository is from an untrusted source. Click Trust to continue. The repository is open source so you can review the Terraform before approving.
Paste the command into the shell and press Enter.
The script runs Terraform in your project and performs the initial setup:
Enables five Google APIs: Cloud Resource Manager, IAM, IAM Credentials, STS, and Service Usage
Creates a porter-manager-* service account that Porter impersonates
Creates a porter-pool-* Workload Identity Pool with a trust policy scoped to your project
Grants three bootstrap IAM roles to the service account so Porter can finish the rest of the configuration itself: roles/serviceusage.serviceUsageAdmin, roles/resourcemanager.projectIamAdmin, and roles/iam.serviceAccountAdmin
Setup takes about 30 seconds.
3
Wait for verification
Porter’s dashboard polls the connection automatically. Once the bootstrap completes, Porter takes over the heavier configuration on your behalf. It enables the remaining APIs needed for cluster provisioning (Compute, Kubernetes Engine, Artifact Registry, Secret Manager, and others) and grants the matching per-service roles to the porter-manager-* service account (Compute Admin, Kubernetes Engine Admin, Artifact Registry Admin, Secret Manager Admin, and others). Once everything is provisioned, the cloud account is marked connected and the status banner turns green.The full Terraform module is open source if you want to inspect every resource Porter creates: porter-dev/gcp-onboarding.
Once your project is connected, Porter provisions and continuously reconciles infrastructure in it: the VPC, Cloud NAT and Cloud Router, the GKE cluster, its node pools, and the cluster load balancer.
Do not modify Porter-managed resources directly in the GCP Console or with gcloud. Out-of-band changes are detected as drift on the next cluster update: Porter will revert them, which can itself disrupt traffic. Changes to settings that GKE cannot update in place may cause the cluster to be replaced entirely, resulting in downtime and the loss of any manually created in-cluster resources.
Settings that can trigger reconciliation or cluster replacement when changed outside of Porter include:
Cloud NAT and Cloud Router — port allocation (min ports per VM, dynamic port allocation), endpoint-independent mapping, TCP timeouts, NAT IP allocation mode and static NAT IPs, source subnetwork ranges
VPC — the cluster VPC and subnet, primary and secondary CIDR ranges, Private Google Access and its associated routes and DNS
GKE control plane — cluster version, private cluster settings (private nodes, endpoint access), master authorized networks and CIDR, workload identity pool, logging and system components, cluster autoscaling, KMS settings
Settings like NAT port allocation and node pool configuration can be changed safely from the Porter dashboard. For any requirement not exposed there (for example, public node IPs to reduce egress cost), contact Porter support before changing it in GCP.
If you previously connected GCP using a service account JSON key, you can switch to Workload Identity Federation with no downtime:
In Porter, navigate to Integrations → Cloud accounts and select your GCP account.
Click Migrate to Workload Identity Federation in the banner at the top of the page.
Follow the same Cloud Shell flow above.
Your existing clusters keep authenticating with the JSON key while the new federation is being verified. Once verified, Porter swaps the credential atomically. There is no service interruption.
Workload Identity Federation is now the active connection between Porter and your GCP project, but your previous service account and its JSON key are still present in your project until you remove them. To finish the migration:
In the GCP Console, open IAM & Admin → Service Accounts.
Find your legacy service account (the one whose key you previously uploaded to Porter — typically named porter-manager, separate from the new porter-manager-* account created during federation).
Delete its JSON key, or delete the entire service account.
Porter no longer needs the legacy account once federation is active. Leaving it in place means an unrotated long-lived key continues to exist in your project.
First, delete any clusters through the Porter dashboard.
In the GCP Console, navigate to IAM & Admin → Workload Identity Federation and delete the porter-pool-* Workload Identity Pool. This immediately invalidates all federated tokens.
Optionally, also delete the porter-manager-* service account under IAM & Admin → Service Accounts for full cleanup.
Porter connects to Azure using workload identity federation. You create a managed identity that trusts a Porter-managed OIDC issuer. Porter generates short-lived JWT tokens using this OIDC isser and exchanges them with Azure for short-lived Azure tokens.
In the Porter dashboard, click Connect a new account and select Azure. Porter generates a one-time setup command with your OIDC subject and issuer already substituted. Keep this open — you’ll paste it into your terminal in the next step.
2
Run the setup commands
Copy the commands shown in the dashboard and run it in your terminal. The commands look like:
# Authenticate the Azure CLIaz login# Download the setup scriptcurl -O https://install.porter.run/scripts/setup-azure-porter-wif.sh# Make it executablechmod +x setup-azure-porter-wif.sh# Run the script with the OIDC subject and issuer from Porter./setup-azure-porter-wif.sh \ --subject <oidc-subject-from-porter> \ --issuer <oidc-issuer-from-porter>
The script performs the initial setup in your Azure account:
Enables the required Azure resource providers:
Microsoft.Capacity
Microsoft.Compute
Microsoft.ContainerRegistry
Microsoft.ContainerService
Microsoft.ManagedIdentity
Microsoft.Network
Microsoft.OperationalInsights
Microsoft.OperationsManagement
Microsoft.ResourceGraph
Microsoft.Resources
Microsoft.Storage
Creates the custom porter-aks-restricted role and grants all subscription actions except:
Microsoft.Authorization/elevateAccess/Action
Microsoft.Blueprint/blueprintAssignments/write
Microsoft.Blueprint/blueprintAssignments/delete
Microsoft.Compute/galleries/share/action
Creates the azure-porter-federated-sp app registration and matching service principal, then assigns the custom role at the subscription scope
Makes the service principal an owner of its own app registration
Adds the Application.ReadWrite.OwnedBy Microsoft Graph application permission and grants admin consent for it. This is the only Graph permission Porter uses, and Porter uses it solely to manage the federated identity credentials on the app registration the service principal owns. Its write access is limited to applications the service principal creates or owns, so Porter cannot modify any other application in your tenant
Adds a federated identity credential on the app registration trusting Porter’s OIDC issuer (audience api://AzureADTokenExchange)
Outputs the app registration’s metadata: Subscription ID, Application (Client) ID, and Tenant ID
Setup can take a few minutes.
If the script fails to grant admin consent automatically, grant it manually in the Azure Portal: App registrations > azure-porter-federated-sp > API permissions > Grant admin consent for Default Directory.
3
Enter app metadata into Porter
Paste the outputted Subscription ID, Application (Client) ID, and Tenant ID back into the Porter dashboard to register the connection.
In the Azure portal, search for App registrations and delete azure-porter-federated-sp
[Optional] Delete the custom role definition created by Porter
This ensures that Porter can no longer access your Azure subscription.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Porter","colors":{"primary":"#5B63B2","light":"#AAB6FF","dark":"#3C4189"},"logo":{"light":"https://mintcdn.com/porter/CtQBkRh1tKAcCdoJ/logo/light.png?fit=max\u0026auto=format\u0026n=CtQBkRh1tKAcCdoJ\u0026q=85\u0026s=5de59d319dc29230f06a5cc0d54518de","dark":"https://mintcdn.com/porter/CtQBkRh1tKAcCdoJ/logo/dark.png?fit=max\u0026auto=format\u0026n=CtQBkRh1tKAcCdoJ\u0026q=85\u0026s=20a106f87d62ff1c1d1cba53466fce37","href":"https://porter.run"},"favicon":"https://mintcdn.com/porter/hk4qFrcZwgdgi3c0/favicon.ico?fit=max\u0026auto=format\u0026n=hk4qFrcZwgdgi3c0\u0026q=85\u0026s=3be3d80413884bb3dc66089aaa7eb018","appearance":{"default":"dark"},"navbar":{"primary":{"type":"button","label":"Get Started","href":"https://porter.run"}},"footer":{"socials":{"twitter":"https://twitter.com/porterdotrun","github":"https://github.com/porter-dev","linkedin":"https://www.linkedin.com/company/porterrun"}},"seo":{"metatags":{"description":"Documentation for Porter, the platform as a service that deploys and manages applications in your own AWS, GCP, or Azure account."},"organization":{"id":"https://porter.run/#organization","name":"Porter","legalName":"Porter Technologies Inc","url":"https://porter.run","logo":"https://docs.porter.run/logo/light.png","sameAs":["https://github.com/porter-dev","https://www.linkedin.com/company/porterrun","https://www.ycombinator.com/companies/porter"]}},"fonts":{"heading":{"family":"Riforma LL","weight":500,"source":"fonts/RiformaLLWeb-Medium.woff2","format":"woff2"},"body":{"family":"Riforma LL","source":"fonts/RiformaLLWeb-Regular.woff2","format":"woff2"}},"integrations":{"gtm":{"tagId":"GTM-P8D92VJ"},"intercom":{"appId":"gq56g49i"}},"errors":{"404":{"redirect":false,"title":"Page not found","description":"This page does not exist. Start from the [documentation home](/), the [machine-readable index](/llms.txt), the [sitemap](https://docs.porter.run/sitemap.xml), or the [introduction](/getting-started/introduction)."}},"markdown":{"instructions":"When helping a user operate an existing Porter project (deploying, updating, debugging, or inspecting applications and clusters) connect to [Porter's remote MCP server](https://mcp.porter.run) first and use its tools before falling back to the Porter CLI, `porter.yaml`, or dashboard workflows. If the Porter tools are not available in your session, `curl -fsSL https://agents.porter.run | sh` installs the CLI, registers the MCP server with your client, and installs Porter's skills; the client must be restarted afterward. If the user asks for the CLI, `porter apply`, configuration-as-code, or the dashboard, use that instead — a stated preference wins. Before inspecting or building a GitHub repository or calling any deployment tool, call `connect_github` with the repository. Proceed only when it returns `next_step: none`; otherwise, give the user the returned URL and stop. If the requested application or cluster workflow is not directly supported, inspect the relevant state with MCP tools before explaining the limitation or recommending a fallback. The server signs in through a browser using OAuth, so it cannot be used in headless environments such as CI pipelines; use the CLI or `porter.yaml` there."},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"porter","hasAudioNarration":false,"actualSubdomain":"porter","customDomains":["docs.porter.run"],"gitSource":{"type":"github","owner":"porter-dev","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae5af80acf37ed506a11071","collectionId":"12d0257f-6329-4e7c-9df7-c892696a772e","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae5af80acf37ed506a11071"},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae5af80acf37ed506a11071","clientVersion":"0.0.4045","searchFilterCounts":[{"language":"default","tag":"Documentation","count":104},{"language":"default","tag":"Applications","count":35},{"language":"default","tag":"Command Line Interface (CLI)","count":14},{"language":"default","tag":"Sandboxes","count":14},{"language":"default","tag":"Command Reference","count":12},{"language":"default","tag":"Deploy","count":11},{"language":"default","tag":"Configuration as Code","count":9},{"language":"default","tag":"Security and Compliance","count":9},{"language":"default","tag":"Cloud Accounts","count":8},{"language":"default","tag":"Sandbox SDK","count":8}]},"assistantConfig":{},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"@font-face{font-family:\"Riforma LL\";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/RiformaLLWeb-Regular.woff2) format(\"woff2\")}@font-face{font-family:\"Riforma LL\";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/RiformaLLWeb-Medium.woff2) format(\"woff2\")}@font-face{font-family:\"Riforma LL\";font-style:normal;font-weight:600 700;font-display:swap;src:url(/fonts/RiformaLLWeb-Bold.woff2) format(\"woff2\")}@font-face{font-family:\"Riforma Mono\";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/RiformaMonoLLWeb-Regular.woff2) format(\"woff2\")}@font-face{font-family:\"Riforma Mono\";font-style:normal;font-weight:600 700;font-display:swap;src:url(/fonts/RiformaMonoLLWeb-Bold.woff2) format(\"woff2\")}:root{--font-weight-bold:500;--font-weight-semibold:500;--font-family-mono-custom:\"Riforma Mono\"}b,strong,th{font-weight:500}a{font-weight:inherit}"}],"page":{"pagePath":"cloud-accounts/connecting-a-cloud-account","slug":"/cloud-accounts/connecting-a-cloud-account","pageMetadata":{"title":"Connecting a cloud account","sidebarTitle":"Connecting a Cloud Account","description":"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure","href":"/cloud-accounts/connecting-a-cloud-account"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Info,Step,Steps,Tab,Tabs,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Info)_missingMdxReference(`Info`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`Before Porter can create a cluster, you need to grant it access to your cloud account. Porter uses secure credential methods that don’t require storing static API keys.`}),`\n`,_jsxs(Tabs,{children:[_jsxs(Tab,{title:`AWS`,id:`aws`,\"data-child-heading-ids\":`[\"create-the-iam-role\",\"permissions-granted\",\"revoking-access\"]`,children:[_jsxs(_components.p,{children:[`Porter uses AWS IAM role assumption via the `,_jsx(_components.code,{children:`AssumeRole`}),` `,_jsx(_components.a,{href:`https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html`,children:`operation`}),` to access your account. You create a role in your AWS account and declare that you trust Porter to assume it. This eliminates static credentials and makes access easy to revoke.`]}),_jsx(Heading,{level:`2`,id:`create-the-iam-role`,children:`Create the IAM Role`}),_jsxs(Steps,{children:[_jsxs(Step,{title:`Enter your AWS Account ID`,children:[_jsxs(_components.p,{children:[`After selecting AWS as your cloud provider, log into your `,_jsx(_components.a,{href:`https://console.aws.amazon.com`,children:`AWS Console`}),` and find your 12-digit Account ID in the top-right corner.`]}),_jsxs(_components.p,{children:[`Enter this ID in Porter and click `,_jsx(_components.strong,{children:`Grant Permissions`}),`.`]})]}),_jsxs(Step,{title:`Create the CloudFormation stack`,children:[_jsxs(_components.p,{children:[`Porter opens the AWS CloudFormation console in a new tab to create a stack that provisions the `,_jsx(_components.code,{children:`porter-manager`}),` IAM role.`]}),_jsx(Warning,{children:_jsx(_components.p,{children:`If the popup is blocked, check your browser settings and allow popups from Porter.`})}),_jsxs(_components.p,{children:[`Scroll to the bottom of the CloudFormation page, check the `,_jsx(_components.strong,{children:`I acknowledge that AWS CloudFormation might create IAM resources`}),` box, and click `,_jsx(_components.strong,{children:`Create Stack`}),`.`]}),_jsx(_components.p,{children:`Wait for the stack creation to complete (this takes a few minutes).`})]})]}),_jsx(Info,{children:_jsx(_components.p,{children:`The IAM role must remain in your AWS account for Porter to manage your infrastructure. Deleting it will prevent Porter from making changes.`})}),_jsx(Heading,{level:`2`,id:`permissions-granted`,children:`Permissions Granted`}),_jsx(_components.p,{children:`The CloudFormation stack creates an IAM role with permissions to:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Create and manage EKS clusters`}),`\n`,_jsx(_components.li,{children:`Create and manage VPCs, subnets, and security groups`}),`\n`,_jsx(_components.li,{children:`Create and manage ECR repositories`}),`\n`,_jsx(_components.li,{children:`Create and manage IAM roles for cluster operations`}),`\n`,_jsx(_components.li,{children:`Request service quota increases`}),`\n`]}),_jsx(Info,{children:_jsx(_components.p,{children:`If you need Porter to operate with more restricted permissions, contact us through the support widget to inquire about Porter Enterprise.`})}),_jsx(Heading,{level:`2`,id:`revoking-access`,children:`Revoking Access`}),_jsx(_components.p,{children:`To revoke Porter’s access:`}),_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`First, delete any clusters through the Porter dashboard`}),`\n`,_jsxs(_components.li,{children:[`Navigate to `,_jsx(_components.strong,{children:`CloudFormation Stacks`}),` in your AWS console`]}),`\n`,_jsxs(_components.li,{children:[`Select the stack named `,_jsx(_components.code,{children:`PorterRole`}),` and click `,_jsx(_components.strong,{children:`Delete`})]}),`\n`]}),_jsx(_components.p,{children:`This removes the IAM role and prevents Porter from accessing your account.`})]}),_jsxs(Tab,{title:`GCP`,id:`gcp`,\"data-child-heading-ids\":`[\"prerequisites\",\"connect-your-gcp-project\",\"porter-managed-infrastructure\",\"migrating-from-a-service-account-json\",\"after-migration\",\"revoking-access-2\"]`,children:[_jsxs(_components.p,{children:[`Porter connects to GCP using `,_jsx(_components.a,{href:`https://cloud.google.com/iam/docs/workload-identity-federation`,children:`Workload Identity Federation`}),`. Workload Identity Federation offers a mechanism for Porter to connect with your GCP project without requiring any static keys. Setup runs in `,_jsx(_components.a,{href:`https://cloud.google.com/shell`,children:`Google Cloud Shell`}),` with a single command Porter generates for your project.`]}),_jsx(Heading,{level:`2`,id:`prerequisites`,children:`Prerequisites`}),_jsxs(_components.p,{children:[`Your GCP project needs an active `,_jsx(_components.a,{href:`https://console.cloud.google.com/billing`,children:`billing account`}),` attached. Porter cannot provision infrastructure without one.`]}),_jsxs(_components.p,{children:[`The Google account running the setup must have these project-level roles (or `,_jsx(_components.code,{children:`roles/owner`}),`, which covers all of them):`]}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`roles/serviceusage.serviceUsageAdmin`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`roles/iam.serviceAccountAdmin`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`roles/resourcemanager.projectIamAdmin`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`roles/iam.workloadIdentityPoolAdmin`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`roles/storage.admin`})}),`\n`]}),_jsx(Heading,{level:`2`,id:`connect-your-gcp-project`,children:`Connect Your GCP Project`}),_jsxs(Steps,{children:[_jsx(Step,{title:`Enter your GCP Project ID`,children:_jsxs(_components.p,{children:[`In Porter, select GCP. Enter your `,_jsx(_components.a,{href:`https://console.cloud.google.com`,children:`GCP project ID`}),` (visible at the top of any page in the GCP Console) and click `,_jsx(_components.strong,{children:`Connect`}),`. Porter generates a one-time setup command scoped to this integration.`]})}),_jsxs(Step,{title:`Run the setup in Cloud Shell`,children:[_jsx(_components.p,{children:`In the Porter dashboard:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Copy the command shown in the `,_jsx(_components.strong,{children:`Run Setup in Cloud Shell`}),` panel.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Open Cloud Shell`}),` to launch a new tab with the `,_jsx(_components.a,{href:`https://github.com/porter-dev/gcp-onboarding`,children:`porter-dev/gcp-onboarding`}),` repository pre-loaded.`]}),`\n`,_jsxs(_components.li,{children:[`Cloud Shell will warn that the repository is from an untrusted source. Click `,_jsx(_components.strong,{children:`Trust`}),` to continue. The repository is open source so you can review the Terraform before approving.`]}),`\n`,_jsx(_components.li,{children:`Paste the command into the shell and press Enter.`}),`\n`]}),_jsx(_components.p,{children:`The script runs Terraform in your project and performs the initial setup:`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Enables five Google APIs: Cloud Resource Manager, IAM, IAM Credentials, STS, and Service Usage`}),`\n`,_jsxs(_components.li,{children:[`Creates a `,_jsx(_components.code,{children:`porter-manager-*`}),` service account that Porter impersonates`]}),`\n`,_jsxs(_components.li,{children:[`Creates a `,_jsx(_components.code,{children:`porter-pool-*`}),` Workload Identity Pool with a trust policy scoped to your project`]}),`\n`,_jsxs(_components.li,{children:[`Grants three bootstrap IAM roles to the service account so Porter can finish the rest of the configuration itself: `,_jsx(_components.code,{children:`roles/serviceusage.serviceUsageAdmin`}),`, `,_jsx(_components.code,{children:`roles/resourcemanager.projectIamAdmin`}),`, and `,_jsx(_components.code,{children:`roles/iam.serviceAccountAdmin`})]}),`\n`]}),_jsx(_components.p,{children:`Setup takes about 30 seconds.`})]}),_jsxs(Step,{title:`Wait for verification`,children:[_jsxs(_components.p,{children:[`Porter’s dashboard polls the connection automatically. Once the bootstrap completes, Porter takes over the heavier configuration on your behalf. It enables the remaining APIs needed for cluster provisioning (Compute, Kubernetes Engine, Artifact Registry, Secret Manager, and others) and grants the matching per-service roles to the `,_jsx(_components.code,{children:`porter-manager-*`}),` service account (Compute Admin, Kubernetes Engine Admin, Artifact Registry Admin, Secret Manager Admin, and others). Once everything is provisioned, the cloud account is marked connected and the status banner turns green.`]}),_jsxs(_components.p,{children:[`The full Terraform module is open source if you want to inspect every resource Porter creates: `,_jsx(_components.a,{href:`https://github.com/porter-dev/gcp-onboarding`,children:`porter-dev/gcp-onboarding`}),`.`]})]})]}),_jsx(Heading,{level:`2`,id:`porter-managed-infrastructure`,children:`Porter-Managed Infrastructure`}),_jsx(_components.p,{children:`Once your project is connected, Porter provisions and continuously reconciles infrastructure in it: the VPC, Cloud NAT and Cloud Router, the GKE cluster, its node pools, and the cluster load balancer.`}),_jsx(Warning,{children:_jsxs(_components.p,{children:[`Do not modify Porter-managed resources directly in the GCP Console or with `,_jsx(_components.code,{children:`gcloud`}),`. Out-of-band changes are detected as drift on the next cluster update: Porter will revert them, which can itself disrupt traffic. Changes to settings that GKE cannot update in place may cause the `,_jsx(_components.strong,{children:`cluster to be replaced entirely`}),`, resulting in downtime and the loss of any manually created in-cluster resources.`]})}),_jsx(_components.p,{children:`Settings that can trigger reconciliation or cluster replacement when changed outside of Porter include:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Cloud NAT and Cloud Router`}),` — port allocation (min ports per VM, dynamic port allocation), endpoint-independent mapping, TCP timeouts, NAT IP allocation mode and static NAT IPs, source subnetwork ranges`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`VPC`}),` — the cluster VPC and subnet, primary and secondary CIDR ranges, Private Google Access and its associated routes and DNS`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`GKE control plane`}),` — cluster version, private cluster settings (private nodes, endpoint access), master authorized networks and CIDR, workload identity pool, logging and system components, cluster autoscaling, KMS settings`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`GKE node pools`}),` — machine type, disk, image type, autoscaling settings, node locations and versions, spot/preemptible flag, OAuth scopes, labels, taints, network tags, GPU settings, upgrade and management settings`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Load balancer`}),` — the external static IP`]}),`\n`]}),_jsx(_components.p,{children:`Settings like NAT port allocation and node pool configuration can be changed safely from the Porter dashboard. For any requirement not exposed there (for example, public node IPs to reduce egress cost), contact Porter support before changing it in GCP.`}),_jsx(Heading,{level:`2`,id:`migrating-from-a-service-account-json`,children:`Migrating from a Service Account JSON`}),_jsx(_components.p,{children:`If you previously connected GCP using a service account JSON key, you can switch to Workload Identity Federation with no downtime:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In Porter, navigate to `,_jsx(_components.strong,{children:`Integrations`}),` → `,_jsx(_components.strong,{children:`Cloud accounts`}),` and select your GCP account.`]}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Migrate to Workload Identity Federation`}),` in the banner at the top of the page.`]}),`\n`,_jsx(_components.li,{children:`Follow the same Cloud Shell flow above.`}),`\n`]}),_jsx(_components.p,{children:`Your existing clusters keep authenticating with the JSON key while the new federation is being verified. Once verified, Porter swaps the credential atomically. There is no service interruption.`}),_jsx(Heading,{level:`3`,id:`after-migration`,children:`After Migration`}),_jsx(_components.p,{children:`Workload Identity Federation is now the active connection between Porter and your GCP project, but your previous service account and its JSON key are still present in your project until you remove them. To finish the migration:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://console.cloud.google.com`,children:`GCP Console`}),`, open `,_jsx(_components.strong,{children:`IAM \u0026 Admin`}),` → `,_jsx(_components.strong,{children:`Service Accounts`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Find your legacy service account (the one whose key you previously uploaded to Porter — typically named `,_jsx(_components.code,{children:`porter-manager`}),`, separate from the new `,_jsx(_components.code,{children:`porter-manager-*`}),` account created during federation).`]}),`\n`,_jsx(_components.li,{children:`Delete its JSON key, or delete the entire service account.`}),`\n`]}),_jsx(_components.p,{children:`Porter no longer needs the legacy account once federation is active. Leaving it in place means an unrotated long-lived key continues to exist in your project.`}),_jsx(Heading,{level:`2`,id:`revoking-access-2`,children:`Revoking Access`}),_jsx(_components.p,{children:`To disconnect Porter from your GCP project:`}),_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`First, delete any clusters through the Porter dashboard.`}),`\n`,_jsxs(_components.li,{children:[`In the `,_jsx(_components.a,{href:`https://console.cloud.google.com`,children:`GCP Console`}),`, navigate to `,_jsx(_components.strong,{children:`IAM \u0026 Admin`}),` → `,_jsx(_components.strong,{children:`Workload Identity Federation`}),` and delete the `,_jsx(_components.code,{children:`porter-pool-*`}),` Workload Identity Pool. This immediately invalidates all federated tokens.`]}),`\n`]}),_jsxs(_components.p,{children:[`Optionally, also delete the `,_jsx(_components.code,{children:`porter-manager-*`}),` service account under `,_jsx(_components.strong,{children:`IAM \u0026 Admin`}),` → `,_jsx(_components.strong,{children:`Service Accounts`}),` for full cleanup.`]})]}),_jsxs(Tab,{title:`Azure`,id:`azure`,\"data-child-heading-ids\":`[\"prerequisites-2\",\"connect-your-azure-subscription\",\"revoking-access-3\"]`,children:[_jsxs(_components.p,{children:[`Porter connects to Azure using `,_jsx(_components.a,{href:`https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation`,children:`workload identity federation`}),`. You create a `,_jsx(_components.a,{href:`https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview`,children:`managed identity`}),` that trusts a Porter-managed OIDC issuer. Porter generates short-lived JWT tokens using this OIDC isser and exchanges them with Azure for short-lived Azure tokens.`]}),_jsx(Heading,{level:`2`,id:`prerequisites-2`,children:`Prerequisites`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`You must have permissions to create app registrations, role definitions, and role assignments in your Azure subscription`}),`\n`,_jsxs(_components.li,{children:[`You must have the `,_jsx(_components.a,{href:`https://learn.microsoft.com/en-us/cli/azure/install-azure-cli`,children:`Azure CLI`}),` and `,_jsx(_components.a,{href:`https://jqlang.github.io/jq/`,children:_jsx(_components.code,{children:`jq`})}),` installed`]}),`\n`]}),_jsx(Heading,{level:`2`,id:`connect-your-azure-subscription`,children:`Connect Your Azure Subscription`}),_jsxs(Steps,{children:[_jsx(Step,{title:`Begin the Azure connection process in Porter`,children:_jsxs(_components.p,{children:[`In the Porter dashboard, click `,_jsx(_components.strong,{children:`Connect a new account`}),` and select `,_jsx(_components.strong,{children:`Azure`}),`. Porter generates a one-time setup command with your OIDC subject and issuer already substituted. Keep this open — you’ll paste it into your terminal in the next step.`]})}),_jsxs(Step,{title:`Run the setup commands`,children:[_jsx(_components.p,{children:`Copy the commands shown in the dashboard and run it in your terminal. The commands look like:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`13`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`13`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Authenticate the Azure CLI`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`az`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` login`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Download the setup script`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`curl`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -O`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` https://install.porter.run/scripts/setup-azure-porter-wif.sh`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Make it executable`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`chmod`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` +x`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` setup-azure-porter-wif.sh`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Run the script with the OIDC subject and issuer from Porter`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`./setup-azure-porter-wif.sh`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --subject`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`oidc-subject-from-porte`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`r`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --issuer`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`oidc-issuer-from-porte`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`r`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`]})})}),_jsx(_components.p,{children:`The script performs the initial setup in your Azure account:`}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Enables the required Azure resource providers:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Microsoft.Capacity`}),`\n`,_jsx(_components.li,{children:`Microsoft.Compute`}),`\n`,_jsx(_components.li,{children:`Microsoft.ContainerRegistry`}),`\n`,_jsx(_components.li,{children:`Microsoft.ContainerService`}),`\n`,_jsx(_components.li,{children:`Microsoft.ManagedIdentity`}),`\n`,_jsx(_components.li,{children:`Microsoft.Network`}),`\n`,_jsx(_components.li,{children:`Microsoft.OperationalInsights`}),`\n`,_jsx(_components.li,{children:`Microsoft.OperationsManagement`}),`\n`,_jsx(_components.li,{children:`Microsoft.ResourceGraph`}),`\n`,_jsx(_components.li,{children:`Microsoft.Resources`}),`\n`,_jsx(_components.li,{children:`Microsoft.Storage`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Creates the custom `,_jsx(_components.code,{children:`porter-aks-restricted`}),` role and grants all subscription actions except:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`Microsoft.Authorization/elevateAccess/Action`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`Microsoft.Blueprint/blueprintAssignments/write`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`Microsoft.Blueprint/blueprintAssignments/delete`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`Microsoft.Compute/galleries/share/action`})}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`Creates the `,_jsx(_components.code,{children:`azure-porter-federated-sp`}),` app registration and matching service principal, then assigns the custom role at the subscription scope`]}),`\n`,_jsx(_components.li,{children:`Makes the service principal an owner of its own app registration`}),`\n`,_jsxs(_components.li,{children:[`Adds the `,_jsx(_components.code,{children:`Application.ReadWrite.OwnedBy`}),` Microsoft Graph application permission and grants admin consent for it. This is the only Graph permission Porter uses, and Porter uses it solely to manage the federated identity credentials on the app registration the service principal owns. Its write access is limited to applications the service principal creates or owns, so Porter cannot modify any other application in your tenant`]}),`\n`,_jsxs(_components.li,{children:[`Adds a federated identity credential on the app registration trusting Porter’s OIDC issuer (audience `,_jsx(_components.code,{children:`api://AzureADTokenExchange`}),`)`]}),`\n`,_jsxs(_components.li,{children:[`Waits for Azure’s `,_jsx(_components.a,{href:`https://devblogs.microsoft.com/identity/designing-for-eventual-consistency-for-microsoft-entra/`,children:`eventually consistent IAM service`}),` to propogate changes.`]}),`\n`,_jsxs(_components.li,{children:[`Outputs the app registration’s metadata: `,_jsx(_components.strong,{children:`Subscription ID`}),`, `,_jsx(_components.strong,{children:`Application (Client) ID`}),`, and `,_jsx(_components.strong,{children:`Tenant ID`})]}),`\n`]}),_jsx(_components.p,{children:`Setup can take a few minutes.`}),_jsx(Info,{children:_jsxs(_components.p,{children:[`If the script fails to grant admin consent automatically, grant it manually in the Azure Portal: `,_jsx(_components.strong,{children:`App registrations`}),` > `,_jsx(_components.strong,{children:`azure-porter-federated-sp`}),` > `,_jsx(_components.strong,{children:`API permissions`}),` > `,_jsx(_components.strong,{children:`Grant admin consent for Default Directory`}),`.`]})})]}),_jsx(Step,{title:`Enter app metadata into Porter`,children:_jsxs(_components.p,{children:[`Paste the outputted `,_jsx(_components.strong,{children:`Subscription ID`}),`, `,_jsx(_components.strong,{children:`Application (Client) ID`}),`, and `,_jsx(_components.strong,{children:`Tenant ID`}),` back into the Porter dashboard to register the connection.`]})})]}),_jsx(Heading,{level:`2`,id:`revoking-access-3`,children:`Revoking Access`}),_jsx(_components.p,{children:`To revoke Porter’s access:`}),_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`In the Azure portal, search for `,_jsx(_components.strong,{children:`App registrations`}),` and delete `,_jsx(_components.strong,{children:`azure-porter-federated-sp`})]}),`\n`,_jsx(_components.li,{children:`[Optional] Delete the custom role definition created by Porter`}),`\n`]}),_jsx(_components.p,{children:`This ensures that Porter can no longer access your Azure subscription.`})]})]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Connecting a cloud account","sidebarTitle":"Connecting a Cloud Account","description":"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure","href":"/cloud-accounts/connecting-a-cloud-account"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Create the IAM Role","slug":"create-the-iam-role","depth":2,"children":[],"tabId":"aws"},{"title":"Permissions Granted","slug":"permissions-granted","depth":2,"children":[],"tabId":"aws"},{"title":"Revoking Access","slug":"revoking-access","depth":2,"children":[],"tabId":"aws"},{"title":"Prerequisites","slug":"prerequisites","depth":2,"children":[],"tabId":"gcp"},{"title":"Connect Your GCP Project","slug":"connect-your-gcp-project","depth":2,"children":[],"tabId":"gcp"},{"title":"Porter-Managed Infrastructure","slug":"porter-managed-infrastructure","depth":2,"children":[],"tabId":"gcp"},{"title":"Migrating from a Service Account JSON","slug":"migrating-from-a-service-account-json","depth":2,"children":[{"title":"After Migration","slug":"after-migration","depth":3,"children":[],"tabId":"gcp"}],"tabId":"gcp"},{"title":"Revoking Access","slug":"revoking-access-2","depth":2,"children":[],"tabId":"gcp"},{"title":"Prerequisites","slug":"prerequisites-2","depth":2,"children":[],"tabId":"azure"},{"title":"Connect Your Azure Subscription","slug":"connect-your-azure-subscription","depth":2,"children":[],"tabId":"azure"},{"title":"Revoking Access","slug":"revoking-access-3","depth":2,"children":[],"tabId":"azure"}],"codeExamples":{}},"jsLinks":[],"subdomain":"porter","siteName":"Porter","title":"Connecting a cloud account - Porter","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-09T18:19:06.069Z","originalFileLocation":"cloud-accounts/connecting-a-cloud-account.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\">\u003cmeta data-mint-head name=\"application-name\" content=\"Porter\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Connecting a cloud account - Porter\">\u003cmeta data-mint-head property=\"og:description\" content=\"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Porter\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://porter.mintlify.app/_mintlify/api/og/v2?division=Cloud+Accounts\u0026amp;title=Connecting+a+cloud+account\u0026amp;description=Grant+Porter+access+to+your+AWS%2C+GCP%2C+or+Azure+account+using+IAM+role+assumption+or+Workload+Identity+Federation+to+provision+infrastructure\u0026amp;theme=fec401156b3cb50700eb4d3f\u0026amp;signature=c95ff95f5e9f28c0ba71ad185b62dd9b1bedaa18c1314ad7cdd39cb017b713d3\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Connecting a cloud account - Porter\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://porter.mintlify.app/_mintlify/api/og/v2?division=Cloud+Accounts\u0026amp;title=Connecting+a+cloud+account\u0026amp;description=Grant+Porter+access+to+your+AWS%2C+GCP%2C+or+Azure+account+using+IAM+role+assumption+or+Workload+Identity+Federation+to+provision+infrastructure\u0026amp;theme=fec401156b3cb50700eb4d3f\u0026amp;signature=c95ff95f5e9f28c0ba71ad185b62dd9b1bedaa18c1314ad7cdd39cb017b713d3\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/porter/NTslyGGtUJjpK6WT/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Porter\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#5B63B2\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/cloud-accounts/connecting-a-cloud-account.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://porter.run/#organization\",\"name\":\"Porter\",\"legalName\":\"Porter Technologies Inc\",\"url\":\"https://porter.run\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://docs.porter.run/logo/light.png\"},\"sameAs\":[\"https://github.com/porter-dev\",\"https://www.linkedin.com/company/porterrun\",\"https://www.ycombinator.com/companies/porter\"]},{\"@type\":\"WebSite\",\"@id\":\"https://docs.porter.run#website\",\"name\":\"Porter\",\"url\":\"https://docs.porter.run\",\"publisher\":{\"@id\":\"https://porter.run/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account#webpage\",\"url\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account\",\"name\":\"Connecting a cloud account\",\"description\":\"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\",\"dateModified\":\"2026-09-09T18:19:06.069Z\",\"isPartOf\":{\"@id\":\"https://docs.porter.run#website\"},\"breadcrumb\":{\"@id\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Documentation\",\"item\":\"https://docs.porter.run/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cloud Accounts\",\"item\":\"https://docs.porter.run/cloud-accounts/overview\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Connecting a cloud account\",\"item\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account#article\",\"headline\":\"Connecting a cloud account\",\"name\":\"Connecting a cloud account\",\"description\":\"Grant Porter access to your AWS, GCP, or Azure account using IAM role assumption or Workload Identity Federation to provision infrastructure\",\"url\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account\",\"mainEntityOfPage\":{\"@id\":\"https://docs.porter.run/cloud-accounts/connecting-a-cloud-account#webpage\"},\"dateModified\":\"2026-09-09T18:19:06.069Z\",\"publisher\":{\"@id\":\"https://porter.run/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.porter.run#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Porter\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Porter","nav":{"global":null,"groups":[{"group":"Documentation","pages":[{"title":"Overview","sidebarTitle":"Overview","href":"/index"},{"group":"Getting Started","pages":[{"title":"Introduction","href":"/getting-started/introduction"},{"title":"Concepts","href":"/getting-started/concepts"},{"title":"Quickstart","href":"/getting-started/quickstart"}]},{"group":"AI Agents \u0026 MCP","pages":[{"title":"MCP Server","sidebarTitle":"MCP Server","href":"/mcp/overview"},{"title":"MCP Server Tools","sidebarTitle":"Tools","href":"/mcp/tools"}]},{"group":"Cloud Accounts","pages":[{"title":"Cloud accounts","sidebarTitle":"Overview","description":"Connect your AWS, GCP, or Azure account to Porter and provision managed Kubernetes clusters, node groups, and networking infrastructure","href":"/cloud-accounts/overview"},{"title":"Connecting a cloud account","sidebarTitle":"Connecting a Cloud Account","href":"/cloud-accounts/connecting-a-cloud-account"},{"title":"Creating a cluster","sidebarTitle":"Creating a Cluster","description":"Provision a managed Kubernetes cluster in your AWS, GCP, or Azure cloud account by selecting a region, machine type, and initial instance count","href":"/cloud-accounts/creating-a-cluster"},{"title":"Node groups","sidebarTitle":"Node Groups","href":"/cloud-accounts/node-groups"},{"title":"Cluster upgrades","sidebarTitle":"Cluster Upgrades","href":"/cloud-accounts/cluster-upgrades"},{"title":"Advanced Cluster Settings","href":"/cloud-accounts/advanced-cluster-settings"},{"title":"Cluster observability","sidebarTitle":"Cluster Observability","href":"/cloud-accounts/cluster-observability"},{"title":"Deleting a cluster","sidebarTitle":"Deleting a Cluster","href":"/cloud-accounts/deleting-a-cluster"}]},{"group":"Applications","pages":[{"group":"Deploy","pages":[{"title":"Deploying applications","href":"/applications/deploy/overview"},{"title":"Connect GitHub","href":"/applications/deploy/connect-github"},{"title":"Types of services","href":"/applications/deploy/types-of-services"},{"title":"Deploy from a GitHub repository","href":"/applications/deploy/deploy-from-github-repo"},{"title":"Deploy from a Docker registry","href":"/applications/deploy/deploy-from-docker-registry"},{"title":"Configuring application services","href":"/applications/deploy/configuring-application-services"},{"title":"Building your application","href":"/applications/deploy/builds"},{"title":"Deploy multiple apps from one build","href":"/applications/deploy/multiple-deploys-from-same-build"},{"title":"Pre-deploy jobs","href":"/applications/deploy/pre-deploy-jobs"},{"title":"Rollbacks","href":"/applications/deploy/rollbacks"},{"title":"Using other CI tools","href":"/applications/deploy/using-other-ci-tools"},{"title":"Cloning an application","hidden":true,"href":"/applications/deploy/duplicating-apps"}]},{"group":"Configuration as Code","pages":[{"title":"Configuration as code with porter.yaml","sidebarTitle":"Overview","href":"/applications/configuration-as-code/overview"},{"title":"porter.yaml reference","sidebarTitle":"Reference","href":"/applications/configuration-as-code/reference"},{"title":"Deploying multiple apps with porter.yaml","href":"/applications/configuration-as-code/addons-porter-yaml"},{"group":"Service Configuration","pages":[{"title":"Web services in porter.yaml","href":"/applications/configuration-as-code/services/web-service"},{"title":"Worker services in porter.yaml","href":"/applications/configuration-as-code/services/worker-service"},{"title":"Job services in porter.yaml","href":"/applications/configuration-as-code/services/job-service"},{"title":"Predeploy in porter.yaml","href":"/applications/configuration-as-code/services/predeploy"},{"title":"Autoscaling in porter.yaml","sidebarTitle":"Autoscaling","href":"/applications/configuration-as-code/services/autoscaling"},{"title":"Connections in porter.yaml","sidebarTitle":"Connections","href":"/applications/configuration-as-code/services/connections"}]}]},{"group":"Environment Groups","pages":[{"title":"Environment groups","href":"/applications/configure/environment-groups"}]},{"group":"Configure","pages":[{"title":"Basic configuration","href":"/applications/configure/basic-configuration"},{"title":"Autoscaling","href":"/applications/configure/autoscaling"},{"title":"Temporal autoscaling","href":"/applications/configure/temporal-autoscaling"},{"title":"HTTPS certificates and custom domains","href":"/applications/configure/custom-domains"},{"title":"Zero-downtime deployments","href":"/applications/configure/zero-downtime-deployments"},{"title":"Advanced networking","href":"/applications/configure/advanced-networking"},{"title":"Secure cloud access","href":"/applications/configure/secure-cloud-access"}]},{"group":"Observability","pages":[{"title":"Monitoring","href":"/applications/observability/monitoring"},{"title":"Logging","href":"/applications/observability/logging"},{"title":"Alerts","href":"/applications/observability/alerts"},{"title":"App metadata environment variables","href":"/applications/observability/app-metadata"},{"title":"Custom metrics autoscaling","href":"/applications/observability/custom-metrics-and-autoscaling"},{"title":"DevOps Agent","sidebarTitle":"DevOps Agent","href":"/applications/observability/devops-agent"}]},{"group":"Debug","pages":[{"title":"Common errors","href":"/applications/debug/common-errors"}]}]},{"group":"Sandboxes","pages":[{"title":"Sandboxes Overview","href":"/sandboxes/overview"},{"title":"Sandboxes Getting Started","href":"/sandboxes/getting-started"},{"title":"Volumes","href":"/sandboxes/volumes"},{"title":"Sandbox Networking","href":"/sandboxes/networking"},{"title":"Sandbox Capacity","href":"/sandboxes/capacity"},{"group":"Sandbox SDK","pages":[{"group":"Python","pages":[{"title":"Python Sandbox SDK quickstart","href":"/sandboxes/sdk/python/quickstart"},{"title":"Python Sandbox SDK volumes","href":"/sandboxes/sdk/python/volumes"},{"title":"Python Sandbox SDK reference","href":"/sandboxes/sdk/python/reference"},{"title":"Python Sandbox SDK errors","href":"/sandboxes/sdk/python/errors"}]},{"group":"TypeScript","pages":[{"title":"TypeScript Sandbox SDK quickstart","href":"/sandboxes/sdk/typescript/quickstart"},{"title":"TypeScript Sandbox SDK volumes","href":"/sandboxes/sdk/typescript/volumes"},{"title":"TypeScript Sandbox SDK reference","href":"/sandboxes/sdk/typescript/reference"},{"title":"TypeScript Sandbox SDK errors","href":"/sandboxes/sdk/typescript/errors"}]}]},{"title":"Sandboxes CLI","href":"/sandboxes/cli"}]},{"group":"Add-ons","pages":[{"title":"Add-ons","sidebarTitle":"Overview","href":"/addons/overview"},{"title":"Datastores","sidebarTitle":"Datastores","href":"/addons/datastores"},{"title":"Custom Helm Charts","sidebarTitle":"Custom Helm Charts","href":"/addons/custom-helm-charts"},{"title":"Third-party observability","sidebarTitle":"Third-party Observability","href":"/addons/third-party-observability"},{"title":"Persistent storage","sidebarTitle":"Storage","href":"/addons/storage"},{"title":"QM","sidebarTitle":"QM","href":"/addons/qm"}]},{"group":"Integrations","pages":[{"title":"Doppler","href":"/integrations/doppler"},{"title":"Infisical","href":"/integrations/infisical"}]},{"group":"Command Line Interface (CLI)","pages":[{"title":"CLI installation","href":"/cli/installation"},{"title":"CLI basic usage","href":"/cli/basic-usage"},{"group":"Command Reference","pages":[{"title":"porter apply","sidebarTitle":"porter apply","href":"/standard/cli/command-reference/porter-apply"},{"title":"porter auth","href":"/standard/cli/command-reference/porter-auth"},{"title":"porter clusters","href":"/standard/cli/command-reference/porter-clusters"},{"title":"porter cloud-accounts","href":"/standard/cli/command-reference/porter-cloud-accounts"},{"title":"porter config","href":"/standard/cli/command-reference/porter-config"},{"title":"porter project","href":"/standard/cli/command-reference/porter-project"},{"title":"porter app","href":"/standard/cli/command-reference/porter-app"},{"title":"porter job","href":"/standard/cli/command-reference/porter-job"},{"title":"porter datastore connect","href":"/standard/cli/command-reference/porter-datastore-connect"},{"title":"porter env","href":"/standard/cli/command-reference/porter-env"},{"title":"porter registry","href":"/standard/cli/command-reference/porter-registry"},{"title":"porter target","href":"/standard/cli/command-reference/porter-target"}]}]},{"group":"Preview Environments","pages":[{"title":"Preview environments","href":"/preview-environments/overview"},{"title":"Preview environment overrides","href":"/preview-environments/defining-overrides"},{"title":"Custom preview environment workflows","href":"/preview-environments/custom-workflows"}]},{"group":"Security and Compliance","pages":[{"title":"Role-based access control","href":"/security-and-compliance/role-based-access-control"},{"title":"Audit logs","href":"/security-and-compliance/audit-logs"},{"title":"AWS permissions required for Porter","sidebarTitle":"AWS Roles \u0026 Permissions","href":"/security-and-compliance/aws-permissions"},{"title":"Static egress IPs","href":"/security-and-compliance/static-egress-ip"},{"title":"Configuring AWS ALB on Porter","sidebarTitle":"Configuring AWS ALB","href":"/security-and-compliance/configuring-alb"},{"title":"Using Cloudflare DNS with Porter","sidebarTitle":"Cloudflare DNS","href":"/security-and-compliance/cloudflare-dns"},{"title":"SOC 2 and HIPAA compliance","href":"/security-and-compliance/soc2-hipaa"},{"title":"Porter IP ranges","sidebarTitle":"Porter's IP Ranges","href":"/security-and-compliance/porter-ip-ranges"},{"title":"Tailscale VPN","sidebarTitle":"Tailscale VPN","href":"/security-and-compliance/tailscale"}]},{"group":"Other Guides","pages":[{"title":"Running GPU workloads","href":"/other/gpu-workloads"},{"title":"Deleting dangling resources","href":"/other/deleting-dangling-resources"},{"title":"AWS VPC peering","sidebarTitle":"AWS VPC Peering","href":"/other/aws-vpc-peering"},{"title":"Kubernetes 101","href":"/other/kubernetes-101"},{"title":"Migrate from Heroku","href":"/other/migrate-from-heroku"}]},{"group":"Terms \u0026 Privacy","pages":[{"title":"Terms of service","href":"/terms-and-privacy/terms-of-service"},{"title":"Privacy policy","href":"/terms-and-privacy/privacy-policy"}]}]}]},"basePath":"","title":"Connecting a cloud account - Porter","buildId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","deploymentId":"dpl_36EDyZCDfRuoUD9af5CH4M1bqY2h","dynamics":[],"chunks":[]}