{"id":19748675,"url":"https://github.com/doitintl/gslack","last_synced_at":"2025-04-30T08:33:37.651Z","repository":{"id":22241156,"uuid":"95008128","full_name":"doitintl/gSlack","owner":"doitintl","description":"Get Slack notifications from Google Cloud Platform","archived":false,"fork":false,"pushed_at":"2022-12-10T17:14:29.000Z","size":803,"stargazers_count":72,"open_issues_count":8,"forks_count":15,"subscribers_count":6,"default_branch":"gslack-firebase","last_synced_at":"2024-08-05T08:08:49.856Z","etag":null,"topics":["gcp","google-cloud-datastore","google-cloud-functions","google-cloud-platform","google-cloud-pubsub","slack"],"latest_commit_sha":null,"homepage":"https://blog.doit-intl.com/gslack-9391be7c191a","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doitintl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-21T13:39:15.000Z","updated_at":"2023-12-23T21:05:34.000Z","dependencies_parsed_at":"2023-01-11T21:32:43.192Z","dependency_job_id":null,"html_url":"https://github.com/doitintl/gSlack","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2FgSlack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2FgSlack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2FgSlack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2FgSlack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doitintl","download_url":"https://codeload.github.com/doitintl/gSlack/tar.gz/refs/heads/gslack-firebase","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224203935,"owners_count":17273019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gcp","google-cloud-datastore","google-cloud-functions","google-cloud-platform","google-cloud-pubsub","slack"],"created_at":"2024-11-12T02:22:55.692Z","updated_at":"2024-11-12T02:22:56.284Z","avatar_url":"https://github.com/doitintl.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gSlack\n\n## Prerequisites\n\n- Have a Google Cloud Platform project with billing \u0026 Cloud Build API enabled\n- Have access to a user with `Owner` role on the project\n- Have `gcloud` SDK and CLI installed on your machine ([quickstart](https://cloud.google.com/sdk/docs/quickstarts))\n- Have [`firebase-tools`](https://firebase.google.com/docs/cli/) CLI installed on your machine\n\n## Generate Slack API Token\n\n- Go to [https://\u003cYOUR_SLACK_TEAM\u003e.slack.com/apps/new/A0F7YS25R-bots]()\n- Enter a name for the bot to post with. (i.e. gcp-alert-service)\n- Click `Add bot integration`.\n- Wait until the UI displays the `API Token` and copy the string (i.e. xxxx-yyyyyyyyyyyy-zzzzzzzzzzzzzzzzzzzzzzzz)\n\n## Initialize Firebase environment\n\n- Make sure you are logged in with your `firebase` CLI tool.\n- Edit `\u003cYOUR_PROJECT_ID\u003e` in [`.firebaserc`](.firebaserc) with your real project ID.\n- Run `$ firebase functions:config:set gslack.api_token=\"xxxx-yyyyyyyyyyyy-zzzzzzzzzzzzzzzzzzzzzzzz\"` (Replace with your slack API token)\n\n## Deployment\n\n- Make sure your `gcloud` SDK and CLI environment is authenticated against the requested GCP project with a user that has Owner permissions.\n- Run `$ make create-export PROJECT=\u003cYOUR_PROJECT_ID\u003e` - Replace `\u003cYOUR_PROJECT_ID\u003e` with your project ID (Run once on the first deployment).\n- Deploy the function, run: `$ yarn deploy` or `$ npm run deploy` from the [functions](functions) dir.\n\n## Firestore configuration\n\n- Navigate to your project's Firestore console.\n- Create a new collection named `\"gSlack\"` in Firestore.\n- Add documents to the new collection with the following schema:\n\n| Field Name | Type | Description |\n| ------------- | ------------- | ------------- |\n| channel | string | The destination slack channel, i.e. `general` or `@username` for private messages |\n| disabled | bool | Whether the rule is disabled; disabled rules will not be evaluated by the function |\n| test | string | Must be a a valid JS expression that returns a boolean. If it returns true the test passes. e.g. `$.protoPayload.serviceName==='cloudfunctions.googleapis.com'` |\n| message | string | Must be a a valid JS string template. It will be evaluated to produce the message. e.g. `This is the logname: ${$.logName}` |\n\n- Each document is a rule that will be evaluted by the function and will be posted to the corresponding slack channel if the evaluated test expression passes as `true`.\n- If you want to temporary disable a rule, simply update the `disabled` field to `true`.\n\n## Function Message Payload Example\n\nThe information received by the function for the log entry is something like this:\n\n```\n{\n protoPayload: {\n  @type:  \"type.googleapis.com/google.cloud.audit.AuditLog\"\n  status: {\n  }\n  authenticationInfo: {\n   principalEmail:  \"...@doit-intl.com\"\n  }\n  requestMetadata: {\n   callerIp:  \"...\"\n   callerSuppliedUserAgent:  \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36,gzip(gfe)\"\n  }\n  serviceName:  \"storage.googleapis.com\"\n  methodName:  \"storage.buckets.create\"\n  authorizationInfo: [\n   0: {\n    permission:  \"storage.buckets.create\"\n    granted:  true\n   }\n  ]\n  resourceName:  \"projects/_/buckets/bababab-vadim\"\n  serviceData: {\n   @type:  \"type.googleapis.com/google.iam.v1.logging.AuditData\"\n   policyDelta: {\n    bindingDeltas: [\n     0: {\n      action:  \"ADD\"\n      role:  \"roles/storage.legacyBucketOwner\"\n      member:  \"projectOwner:...\"\n     }\n     1: {\n      action:  \"ADD\"\n      role:  \"roles/storage.legacyBucketOwner\"\n      member:  \"projectEditor:...\"\n     }\n     2: {\n      action:  \"ADD\"\n      role:  \"roles/storage.legacyBucketReader\"\n      member:  \"projectViewer:...\"\n     }\n    ]\n   }\n  }\n  request: {\n   defaultObjectAcl: {\n    bindings: [\n     0: {\n      members: [\n       0:  \"projectOwner:...\"\n       1:  \"projectEditor:...\"\n      ]\n      role:  \"roles/storage.legacyObjectOwner\"\n     }\n     1: {\n      members: [\n       0:  \"projectViewer:...\"\n      ]\n      role:  \"roles/storage.legacyObjectReader\"\n     }\n    ]\n    @type:  \"type.googleapis.com/google.iam.v1.Policy\"\n   }\n  }\n }\n insertId:  \"552D5EE8A9ED9.A65A379.EF01047D\"\n resource: {\n  type:  \"gcs_bucket\"\n  labels: {\n   storage_class:  \"\"\n   location:  \"US-CENTRAL1\"\n   bucket_name:  \"bababab-vadim\"\n   project_id:  \"...\"\n  }\n }\n timestamp:  \"2017-06-26T05:07:46.673Z\"\n severity:  \"NOTICE\"\n logName:  \"projects/.../logs/cloudaudit.googleapis.com%2Factivity\"\n receiveTimestamp:  \"2017-06-26T05:07:54.586745618Z\"\n}\n```\n\n## Fiestore Rules examples\n\n### Google Cloud Storage Bucket Created/Deleted\n\n* Display bucket name, created/deleted, location, project and by who.\n\n* Document ID: `bucket-create-delete`:\n\n* Document Fields:\n\n    ```\n        channel: \"general\",\n        disabled: false,\n        test: \"$.protoPayload.serviceName==='storage.googleapis.com' \u0026\u0026 ( $.protoPayload.methodName==='storage.buckets.create' || $.protoPayload.methodName==='storage.buckets.delete')\",\n        message: \"Bucket '${$.resource.labels.bucket_name}' was ${$.protoPayload.methodName==='storage.buckets.create'?'created':'deleted'} at location '${$.resource.labels.location}' by '${$.protoPayload.authenticationInfo.principalEmail}' in project '${$.resource.labels.project_id}'\",\n        attachments: null\n\n    ```\n\n* [Slack Message Formatting](https://api.slack.com/docs/message-formatting)\n\n    Use the attachments field (type of array of maps) to add Slack message attachments instead of the default text message.\n\n    One of 'message' or 'attachments' fields must not be null.\n\n    ```\n        channel: \"general\",\n        disabled: false,\n        test: \"$.protoPayload.serviceName==='storage.googleapis.com' \u0026\u0026 ( $.protoPayload.methodName==='storage.buckets.create' || $.protoPayload.methodName==='storage.buckets.delete')\",\n        message: null,\n        attachments: [\n            {\n                title: \"Cloud Storage Notification\",\n                color: \"${$.protoPayload.methodName==='storage.buckets.create'?'#36a64f':'#de1738'}\",\n                fields: [\n                    {\n                        short: true,\n                        title: \"Operation\",\n                        value: \"${$.protoPayload.methodName==='storage.buckets.create'?'Create':'Delete'}\"\n                    },\n                    {\n                        short: true,\n                        title: \"Resource Name\",\n                        value: \"${$.resource.labels.bucket_name}\"\n                    },\n                    {\n                        short: true,\n                        title: \"Project ID\",\n                        value: \"${$.resource.labels.project_id}\"\n                    },\n                    {\n                        short: true,\n                        title: \"User\",\n                        value: \"${$.protoPayload.authenticationInfo.principalEmail}\"\n                    },\n                ]\n            }\n        ]\n    ```\n\n    ![alt text](./tutorial/FormattingDocument.png)\n    ![alt text](./tutorial/FormattingResult.png)\n\n\n### Google Compute Engine Instance Started/Stopped\n\n* Display instance name, started/stopped, zone, project and by who.\n\n* Document ID: `gce-start-stop`:\n\n* Document Fields:\n\n    ```\n        channel: \"devops\",\n        disabled: false,\n        test: \"$.protoPayload.serviceName==='compute.googleapis.com' \u0026\u0026 ( $.protoPayload.methodName==='v1.compute.instances.start' || $.protoPayload.methodName==='v1.compute.instances.stop') \u0026\u0026 $.operation.last\",\n        message: \"Instance '${$.protoPayload.resourceName.split('/').slice(-1)[0]}' was ${$.protoPayload.methodName==='v1.compute.instances.start'?'started':'stopped'} at zone '${$.resource.labels.zone}' by '${$.protoPayload.authenticationInfo.principalEmail}' in project '${$.resource.labels.project_id}'\",\n        attachments: null\n    ```\n\n### Google App Engine New Version Deployed\n\n* Display project, module, version and by who.\n\n* Document ID: `gae-new-version`:\n\n* Document Fields:\n\n    ```\n        channel: \"@user\",\n        disabled: false,\n        test: \"$.protoPayload.serviceName==='appengine.googleapis.com' \u0026\u0026 $.protoPayload.methodName==='google.appengine.v1.Versions.CreateVersion' \u0026\u0026 $.operation.last\",\n        message: \"Google AppEngine version created with version ID '${$.resource.labels.version_id}' for module '${$.resource.labels.module_id}' by '${$.protoPayload.authenticationInfo.principalEmail}' in project '${$.resource.labels.project_id}'\",\n        attachments: null\n    ```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoitintl%2Fgslack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoitintl%2Fgslack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoitintl%2Fgslack/lists"}