<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Secure CloudOps]]></title><description><![CDATA[Secure CloudOps]]></description><link>https://cloudopsjournals.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 08 Nov 2026 09:34:19 GMT</lastBuildDate><atom:link href="https://cloudopsjournals.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Deploying a Static Website to Google Cloud Storage using GitHub Actions and Workload Identity Federation (Without Service Account Keys)]]></title><description><![CDATA[Deploying a static website to Google Cloud Storage (GCS) is straightforward. However, manually uploading files after every change quickly becomes…]]></description><link>https://cloudopsjournals.hashnode.dev/deploying-a-static-website-to-google-cloud-storage-using-github-actions-and-workload-identity-federation-without-service-account-keys</link><guid isPermaLink="true">https://cloudopsjournals.hashnode.dev/deploying-a-static-website-to-google-cloud-storage-using-github-actions-and-workload-identity-federation-without-service-account-keys</guid><dc:creator><![CDATA[Punya Manchanda]]></dc:creator><pubDate>Wed, 22 Jul 2026 10:01:50 GMT</pubDate><content:encoded><![CDATA[<h1>Introduction</h1>
<p>Deploying a static website to Google Cloud Storage (GCS) is straightforward. However, manually uploading files after every change quickly becomes inefficient and error-prone.</p>
<p>A better solution is to automate deployments using <strong>GitHub Actions</strong> while following Google's recommended authentication approach: <strong>Workload Identity Federation (WIF)</strong>.</p>
<p>Unlike the traditional method of storing a service account JSON key in GitHub Secrets, WIF uses <strong>short-lived credentials</strong> issued through OpenID Connect (OIDC). This improves security by eliminating long-lived secrets.</p>
<h2>ARCHITECTURE</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6a602f2b63256ad7e7744b77/bb53a937-c224-4c6d-ae00-7ecd3cf59ec7.png" alt="" style="display:block;margin:0 auto" />

<h1>Prerequisites</h1>
<h3>Before starting, ensure you have:</h3>
<ul>
<li><p>A Google Cloud Project</p>
</li>
<li><p>A GitHub repository</p>
</li>
<li><p>A static website (HTML/CSS/JS)</p>
</li>
<li><p>A Google Cloud Storage bucket</p>
</li>
<li><p>Billing enabled</p>
</li>
<li><p>GitHub Actions enabled</p>
</li>
</ul>
<h2>Step 1 – Create the Storage Bucket</h2>
<p>Create a bucket that will host your website. Enable "Uniform Bucket-Level Access (UBLA)" . This simplifies permission management using IAM instead of ACLs.</p>
<h2>Step 2 – Create a Service Account</h2>
<p>Create a dedicated service account for GitHub deployments.</p>
<p>Example: github-gcs-sync</p>
<p>Grant the required permissions. For this deployment I assigned:<br /><strong>Storage Admin</strong> Depending on your requirements, a more restrictive role such as Storage Object Admin may also be appropriate.</p>
<h2>Step 3 – Configure Workload Identity Federation</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6a602f2b63256ad7e7744b77/bc624010-a50f-4412-b98d-1ad9de4e39f6.png" alt="" style="display:block;margin:0 auto" />

<p>Create Workload Identity Pool &amp; Workload Identity Provider</p>
<p>Configure GitHub as the OIDC provider. Grant the GitHub repository permission to impersonate the service account using: roles/iam.workloadIdentityUser.</p>
<h2>Step 4 – GitHub Actions Workflow</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6a602f2b63256ad7e7744b77/70c6b361-527d-40b0-9e64-81669f74e556.png" alt="" style="display:block;margin:0 auto" />

<p>Once this workflow is committed to the repository, every push to the <code>main</code> branch automatically deploys the latest website to Google Cloud Storage.</p>
<h2>Challenges I Encountered</h2>
<p>No cloud deployment is complete without troubleshooting! During implementation, I ran into several issues that helped deepen my understanding of Google Cloud IAM and GitHub Actions</p>
<h3>Missing IAM Permissions</h3>
<p>The deployment initially failed with:</p>
<pre><code class="language-plaintext">Permission 'storage.buckets.get' denied
</code></pre>
<p>The issue was resolved by assigning the appropriate Storage IAM role to the service account.</p>
<h2>Security Best Practices</h2>
<ul>
<li><p>Avoided service account JSON keys</p>
</li>
<li><p>Used Workload Identity Federation</p>
</li>
<li><p>Granted least-privilege IAM roles</p>
</li>
<li><p>Enabled Uniform Bucket-Level Access</p>
</li>
<li><p>Automated deployments through GitHub Actions</p>
</li>
<li><p>Kept credentials temporary using OIDC</p>
</li>
</ul>
<hr />
<h2>Results</h2>
<p>With the pipeline in place, every push to the <code>main</code> branch automatically:</p>
<ul>
<li><p>Authenticates securely using OIDC</p>
</li>
<li><p>Exchanges the token through Workload Identity Federation</p>
</li>
<li><p>Impersonates the Google Cloud service account</p>
</li>
<li><p>Uploads the latest website files to Google Cloud Storage</p>
</li>
</ul>
<p>No manual uploads are required.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6a602f2b63256ad7e7744b77/6bf5ae13-e158-4b24-808c-d359f0ba5145.png" alt="" style="display:block;margin:0 auto" />

<h2>Conclusion</h2>
<p>Building a CI/CD pipeline using GitHub Actions and Workload Identity Federation not only simplified website deployment but also aligned with Google's security best practices.</p>
<p>For anyone deploying applications or static websites on Google Cloud, adopting keyless authentication through Workload Identity Federation is a worthwhile investment. It reduces operational overhead, strengthens security, and provides a scalable foundation for future cloud projects.</p>
<hr />
<h2>Tags</h2>
<p><code>Google Cloud</code> • <code>GitHub Actions</code> • <code>Workload Identity Federation</code> • <code>Google Cloud Storage</code> • <code>CI/CD</code> • <code>Cloud Security</code> • <code>DevOps</code> • <code>IAM</code></p>
]]></content:encoded></item></channel></rss>