Skip to content

fix(calendar): remove hardcoded api key and inject via env var#623

Open
TineoC wants to merge 2 commits intokubernetes:masterfrom
TineoC:fix/remove-hardcoded-api-key
Open

fix(calendar): remove hardcoded api key and inject via env var#623
TineoC wants to merge 2 commits intokubernetes:masterfrom
TineoC:fix/remove-hardcoded-api-key

Conversation

@TineoC
Copy link
Contributor

@TineoC TineoC commented Jan 16, 2026

This PR addresses the security issue of having a hardcoded Google Calendar API key in the source code and improves the robustness of the implementation.

Changes

  • Removed Hardcoded Key: The API key has been removed from static/js/calendar.js.
  • Flexible Key Injection: The key is now injected into the calendar script with the following priority:
    1. HUGO_GOOGLE_CALENDAR_API_KEY environment variable.
    2. google_calendar_api_key site parameter in hugo.yaml.
  • Fixed Template Bug: Replaced the Hugo js filter with jsonify | safeJS to correctly handle empty strings (previously it rendered an empty object {}, which was truthy in JS and caused 400 errors).
  • Improved Debugging: Added masked logging (AIza...) in the browser console to verify which key is being used without exposing it entirely.
  • Graceful Degradation: The renderCalendar function now properly detects missing keys and displays a Bootstrap alert instead of attempting a failed API call.
  • Production Build Enforcement: For production builds, the build will fail if no API key is set, ensuring that we don't accidentally deploy a broken calendar.

Setup Instructions

1. Google Cloud Console (Obtain API Key)

  1. Log in to the Google Cloud Console.
  2. Select your project.
  3. Navigate to APIs & Services > Credentials.
  4. Click + CREATE CREDENTIALS and select API key.
  5. Copy the generated key (should start with AIza).
  6. (Recommended) Click Edit API key to add restrictions:
    • API restrictions: Select "Google Calendar API".
    • Website restrictions: Add kubernetes.dev and your Netlify preview domains.

2. Netlify Dashboard

  1. Log in to your Netlify dashboard.
  2. Select the kubernetes-contributor-site site.
  3. Navigate to Site configuration > Environment variables.
  4. Click Add a variable.
  5. Key: HUGO_GOOGLE_CALENDAR_API_KEY
  6. Value: Enter the valid Google API key (AIza...).
  7. Click Create variable.
  8. Trigger a new deploy for the changes to take effect.

Local Development

For local development, the calendar will show a placeholder message by default. To test functionality locally:

  1. Obtain a valid API key.
  2. Run the server with the environment variable:
    export HUGO_GOOGLE_CALENDAR_API_KEY="AIza..."
    hugo server
    Alternatively, use netlify dev if you have the CLI linked.

Closes #45

@k8s-ci-robot k8s-ci-robot added the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jan 16, 2026
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: TineoC
Once this PR has been reviewed and has the lgtm label, please assign stmcginnis for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jan 16, 2026
@TineoC TineoC force-pushed the fix/remove-hardcoded-api-key branch from 71e96f0 to eefacc4 Compare January 16, 2026 20:05
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jan 16, 2026
@TineoC
Copy link
Contributor Author

TineoC commented Jan 16, 2026

Before merging this changes. Please follow the steps mentioned in "Production Setup Instructions (Netlify)"

@TineoC TineoC force-pushed the fix/remove-hardcoded-api-key branch from b315ccc to 6b4e71d Compare January 16, 2026 20:13
Copy link
Member

@lmktfy lmktfy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial feedback

hugo.yaml Outdated

# Everything below this are Site Params
params:
google_calendar_api_key: 'PLACEHOLDER_VALUE'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this addition?

Copy link
Contributor Author

@TineoC TineoC Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for allowing devs add their Google Calendar keys for local development. but is simpler to just use them in prod. I agree with you

<script src='{{ .Site.BaseURL }}/js/calendar.js'></script>
<script>
renderCalendar();
{{ $apiKey := getenv "HUGO_GOOGLE_CALENDAR_API_KEY" | default .Site.Params.google_calendar_api_key | default "" }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the requirement conditional on whether it is a production build?


if (!apiKey || apiKey === 'PLACEHOLDER_VALUE') {
console.warn('Google Calendar API key is missing. Calendar will not render.');
calendarEl.innerHTML = '<div style="padding: 20px; border: 1px solid #ccc; background: #f9f9f9; text-align: center;">Community Calendar is not available in this environment (missing API Key).</div>';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid embedding CSS here

@TineoC TineoC requested a review from lmktfy January 18, 2026 16:13
<script>
renderCalendar();
{{ if hugo.IsProduction }}
{{ $apiKey := getenv "HUGO_GOOGLE_CALENDAR_API_KEY" | default "" }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's how I'd do it

  • Always try to fetch the value
  • If not production, it doesn't matter
  • If it's missing *in production", call errorf to outright fail the build

document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');

if (!calendarEl) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trick: we can set eg data-isproduction on the root <html> element. But we only do that for production builds, and then client side we know if a calendar / API key is expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like this?

<html {{ if hugo.IsProduction }}data-isproduction="true"{{ end }}>

@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Jan 19, 2026
@TineoC TineoC requested a review from lmktfy January 29, 2026 02:05
@TineoC
Copy link
Contributor Author

TineoC commented Feb 7, 2026

@mrbobbytables @mfahlandt @stmcginnis Who would be the best person to reach out to for providing and setting the GOOGLE_CALENDAR_API_KEY in the production environment (Netlify) of the webpage?

@k8s-ci-robot k8s-ci-robot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Feb 12, 2026
@jberkus
Copy link
Contributor

jberkus commented Feb 12, 2026

@mrbobbytables @mfahlandt @stmcginnis Who would be the best person to reach out to for providing and setting the GOOGLE_CALENDAR_API_KEY in the production environment (Netlify) of the webpage?

@ameukam ?

@ameukam
Copy link
Member

ameukam commented Feb 12, 2026

@mrbobbytables @mfahlandt @stmcginnis Who would be the best person to reach out to for providing and setting the GOOGLE_CALENDAR_API_KEY in the production environment (Netlify) of the webpage?

@ameukam ?

That will be @kubernetes/steering-committee which is the current admin group of the Google Workspace org we use: https://github.com/kubernetes/steering#google-workspace

@BenTheElder
Copy link
Member

@BenTheElder
Copy link
Member

Though steering doesn't have access to the Netlify side, just the Google Workspace.

@TineoC
Copy link
Contributor Author

TineoC commented Mar 11, 2026

@katcosgrove @aojea @soltysh Hi! we need to set up a Google API Key for our Calendar to remove this public key for being stored in the source code.

What needs to be done?

  • Create a Google Calendar key behind the K8s Google Workspace
  • Store it securely in Netflify. (from our SIG the only person I know has access to it is @reylejano there could be more).

@soltysh
Copy link
Contributor

soltysh commented Mar 13, 2026

This is being handled in this slack thread.

@lmktfy
Copy link
Member

lmktfy commented Mar 15, 2026

/uncc

Happy to approve this change once it's ready for that. I recommend adding a hold before asking for approval, because the unhold is easier to secure than approval.

@k8s-ci-robot k8s-ci-robot removed the request for review from lmktfy March 15, 2026 16:28
@TineoC
Copy link
Contributor Author

TineoC commented Mar 15, 2026

/hold

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 15, 2026
@reylejano
Copy link
Member

reylejano commented Mar 20, 2026

The Netlify steps are done. The GOOGLE_CALENDAR_API_KEY env var is added and a deploy is triggered

@TineoC
Copy link
Contributor Author

TineoC commented Mar 20, 2026

@reylejano could you double check the preview in netlify?

Is getting 400 error:

{
  "error": {
    "code": 400,
    "message": "API key not valid. Please pass a valid API key.",
    "errors": [
      {
        "message": "API key not valid. Please pass a valid API key.",
        "domain": "global",
        "reason": "badRequest"
      }
    ],
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_INVALID",
        "domain": "googleapis.com",
        "metadata": {
          "service": "calendar-json.googleapis.com"
        }
      },
      {
        "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
        "locale": "en-US",
        "message": "API key not valid. Please pass a valid API key."
      }
    ]
  }
}

@TineoC TineoC force-pushed the fix/remove-hardcoded-api-key branch from 8ec4e20 to 8ae4064 Compare March 20, 2026 21:11
@TineoC TineoC force-pushed the fix/remove-hardcoded-api-key branch from 8ae4064 to 626f561 Compare March 20, 2026 21:12
@TineoC
Copy link
Contributor Author

TineoC commented Mar 20, 2026

#623 (comment) @reylejano my bad! the description was incorrect. The right key is: HUGO_GOOGLE_CALENDAR_API_KEY

@reylejano
Copy link
Member

#623 (comment) @reylejano my bad! the description was incorrect. The right key is: HUGO_GOOGLE_CALENDAR_API_KEY

I changed it to the right key

@TineoC TineoC force-pushed the fix/remove-hardcoded-api-key branch from abb1d95 to 1ccdc9c Compare March 21, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

google calendar api key

8 participants