0

Setup is using the GKE notifications feature which uses a pub/sub topic, in return this will be using a cloud function to push the notifications (security, upgrade and upgrade available events) into a google chat room via a webhook.

Has anyone got any code for the cloud function to do this? Only thing I can find online is for slack.

Code generated by chatgpt which seems to deploy ok without errors but doesn't do anything (pub sub and topic are setup correctly too)

One using python code:

    import base64
import json
import os
import requests
import sys


def process_event(gchat_data, webhook_url):
    headers = {
        "Content-Type": "application/json",
    }
    response = requests.post(webhook_url, data=json.dumps(gchat_data), headers=headers)
    if response.status_code != 200:
        raise Exception(f"Failed to send Google Chat notification: {response.text}")


def notify_gchat(event, context):
    """Background Cloud Function to be triggered by Pub/Sub.
    Args:
        event (dict): The dictionary with data specific to this type of
            event. The `data` field contains the PubsubMessage message. The
            `attributes` field will contain custom attributes if there are any.
        context (google.cloud.functions.Context): The Cloud Functions event
            metadata. The `event_id` field contains the Pub/Sub message ID. The
            `timestamp` field contains the publish time.
    """
    print(f"This Function was triggered by messageId {context.event_id} published at {context.timestamp}")

    if "data" in event:
        event_data = base64.b64decode(event["data"]).decode("utf-8")
        attributes = event["attributes"]
        cluster = attributes.get("cluster_name")
        cluster_resource = json.loads(attributes.get("payload", "{}")).get("resourceType")
        location = attributes.get("cluster_location")
        project = attributes.get("project_id")
        webhook_url = os.getenv("GOOGLE_CHAT_WEBHOOK_URL")

        if "UpgradeEvent" in attributes.get("type_url", ""):
            current_version = json.loads(attributes.get("payload", "{}")).get("currentVersion")
            start_time = json.loads(attributes.get("payload", "{}")).get("operationStartTime")
            target_version = json.loads(attributes.get("payload", "{}")).get("targetVersion")
            title = "GKE Cluster Upgrade Notification \U0001F525"
            gchat_data = {
                "cards": [
                    {
                        "header": {
                            "title": title,
                            "subtitle": f"Project: {project}\nCluster: {cluster}\nLocation: {location}",
                            "imageUrl": "https://example.com/image.png",
                            "imageStyle": "IMAGE",
                        },
                        "sections": [
                            {
                                "widgets": [
                                    {"keyValue": {"topLabel": "Update Type", "content": cluster_resource}},
                                    {"keyValue": {"topLabel": "Current Version", "content": current_version}},
                                    {"keyValue": {"topLabel": "Target Version", "content": target_version}},
                                    {"keyValue": {"topLabel": "Start Time", "content": start_time}},
                                    {"textParagraph": {"text": f"Details:\n{event_data}"}},
                                ]
                            }
                        ],
                    }
                ]
            }
            process_event(gchat_data, webhook_url)
        elif "UpgradeAvailableEvent" in attributes.get("type_url", "") and os.getenv(
                "SEND_UPGRADE_AVAILABLE_NOTIFICATIONS") == "enabled":
            available_version = json.loads(attributes.get("payload", "{}")).get("version")
            title = "GKE Cluster Upgrade Available Notification \U0001F525"
            gchat_data = {
                "cards": [
                    {
                        "header": {
                            "title": title,
                            "subtitle": f"Project: {project}\nCluster: {cluster}\nLocation: {location}",
                            "imageUrl": "https://example.com/image.png",
                            "imageStyle": "IMAGE",
                        },
                        "sections": [
                            {
                                "widgets": [
                                    {"keyValue": {"topLabel": "Eligible Resource", "content": cluster_resource}},
                                    {"keyValue": {"topLabel": "Eligible Version", "content": available_version}},
                                    {"textParagraph": {"text": f"Details:\n{event_data}"}},
                                ]
                            }
                        ],
                    }
                ]
            }
            process_event(gchat_data, webhook_url)
        else:
            print("Event was neither UpgradeEvent nor UpgradeAvailableEvent, or notifications are disabled.")
            return
    else:
        print("No event data provided. Exiting.")
        return

And another using nodejs:

const axios = require('axios');
const url = process.env.GOOGLE_CHAT_WEBHOOK;

const allowedTypeURLs = [
  'type.googleapis.com/google.container.v1beta1.SecurityBulletinEvent',
  'type.googleapis.com/google.container.v1beta1.UpgradeAvailableEvent',
  'type.googleapis.com/google.container.v1beta1.UpgradeEvent'
];

module.exports.notify_gchat = async (pubSubEvent, context) => {
  const data = decode(pubSubEvent.data);

  if (isAllowedType(pubSubEvent.attributes)) {
    const message = createGoogleChatMessage(data, pubSubEvent.attributes);
    await axios.post(url, message);
  }
};

const decode = (data) => {
  return Buffer.from(data, 'base64').toString();
}

const isAllowedType = (attributes) => {
  if (allowedTypeURLs.length == 0) {
    return true;
  }
  for (var x in allowedTypeURLs) {
    if (attributes['type_url'] == allowedTypeURLs[x]) {
      return true;
    }
  }
  return false;
}

const createGoogleChatMessage = (data, attributes) => {
  let sections = [];
  for (var key in attributes) {
    if (attributes.hasOwnProperty(key)) {
      sections.push({
        "widgets": [
          {
            "keyValue": {
              "topLabel": key,
              "content": attributes[key]
            }
          }
        ]
      });
    }
  }

  const message = {
    "cards": [
      {
        "header": {
          "title": "Notification from Pub/Sub",
          "subtitle": data
        },
        "sections": sections
      }
    ]
  };
 
  return message;
}

Which imports this package:

    {
  "name": "function-name",
  "version": "1.0.0",
  "dependencies": {
    "axios": "^0.23.0"
  }
}

Have the google chat webhook url being inputted correctly too.

terraform-ftw
  • 81
  • 1
  • 12

0 Answers0