{"id":20857432,"url":"https://github.com/unbounce/tattle","last_synced_at":"2026-04-25T10:34:08.612Z","repository":{"id":147465947,"uuid":"123357459","full_name":"unbounce/tattle","owner":"unbounce","description":"Generates AWS CloudWatchEvents for whenever an SSH connection is made to a server","archived":false,"fork":false,"pushed_at":"2019-01-16T18:53:52.000Z","size":293,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-12-26T21:54:11.417Z","etag":null,"topics":["deprecated","owner-platform-services","security","tier-5"],"latest_commit_sha":null,"homepage":"","language":"Go","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/unbounce.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-01T00:01:21.000Z","updated_at":"2025-09-04T16:50:58.000Z","dependencies_parsed_at":"2023-07-24T18:30:11.139Z","dependency_job_id":null,"html_url":"https://github.com/unbounce/tattle","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/unbounce/tattle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbounce%2Ftattle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbounce%2Ftattle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbounce%2Ftattle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbounce%2Ftattle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unbounce","download_url":"https://codeload.github.com/unbounce/tattle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbounce%2Ftattle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32259472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["deprecated","owner-platform-services","security","tier-5"],"created_at":"2024-11-18T04:39:04.925Z","updated_at":"2026-04-25T10:34:08.595Z","avatar_url":"https://github.com/unbounce.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tattle\n\nTattle is a simple, self-contained binary that will report to Amazon Web\nServices (AWS) that a login event has occurred via a Pluggable\nAuthentication Module (PAM).\n\nThe event is sent through CloudWatch Events as it is intended to be an\nasynchronous event for security monitoring services.  Consumers can\nchoose to react to this event by listening with a particular CloudWatch\nEvent rule pattern.\n\nThe producer logic is as follows:\n* This binary is installed into the system.\n* PAM configuration is extended to call the binary on every sshd event\n* User successfully authenticates to server via SSH\n* PAM module calls binary\n* Binary publishes login event to CloudWatch Events\n* User logs out from server\n* PAM module calls binary\n* Binary publishes logout event to CloudWatch Events\n\nAs for consumers, they can listen for either login or logout events (or\nboth) and process the event with myriad AWS services.  For instance, the\nevent could be sent to an SNS topic which alerts an OpsGenie group, or\nto a Lambda function which publishes only login events to a Slack\nchannel to warn administrators.\n\n## Event Payload\n\nThe event pattern is a specific structure so that consumers can read it\nas they wish.\n\nBelow is someone completing an SSH connection to a server:\n\n```json\n{\n  \"detail-type\": \"SSH connection event detected\",\n  \"source\": \"com.unbounce.tattle\",\n  \"resources\": [\n    \"arn:aws:ec2:us-east-1:01234567890:instance/i-abc123abc123\"\n  ],\n  \"detail\": {\n    \"username\": \"ubuntu\",\n    \"remote_host\": \"1.2.3.4\",\n    \"session\": \"opened\"\n  }\n}\n```\n\nBelow is someone closing an SSH connection to a server:\n\n```json\n{\n  \"detail-type\": \"SSH connection event detected\",\n  \"source\": \"com.unbounce.tattle\",\n  \"resources\": [\n    \"arn:aws:ec2:us-east-1:01234567890:instance/i-abc123abc123\"\n  ],\n  \"detail\": {\n    \"username\": \"ubuntu\",\n    \"remote_host\": \"1.2.3.4\",\n    \"session\": \"closed\"\n  }\n}\n```\n\nNote that these events are emitted whenever the SSH daemon is used for\nconnecting to a server, which includes `scp` connections.\n\n## Configuration\n\nAt this time there is no way to configure the binary.  This is on the\nroadmap.  The idea is that the source and detail-type values in the event\npayload will be configurable.\n\n### PAM\n\nAdd the following line to the end of `/etc/pam.d/sshd`:\n\n```\nsession    optional    pam_exec.so /usr/local/bin/tattle\n```\n\nThis has been tested on Ubuntu 14.04 and 16.04 systems.\n\n### EC2\n\nYou will need to update the EC2 server's IAM role to allow `events:PutEvent`\nactions so that tattle can interact with the CloudWatchEvents service.\nThere is no Resource scoping on this action.  Here is a sample policy:\n\n```json\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"AllowCloudWatchEventEmit\",\n            \"Effect\": \"Allow\",\n            \"Action\": \"events:PutEvents\",\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\n\n## What PAM Gives Us\n\nUpon SSH authentication\n```\nPAM_SERVICE=sshd\nPAM_RHOST=10.0.2.2\nPAM_USER=vagrant\nPAM_TYPE=open_session\nPAM_TTY=ssh\n```\n\nUpon SSH logout\n```\nPAM_SERVICE=sshd\nPAM_RHOST=10.0.2.2\nPAM_USER=vagrant\nPAM_TYPE=close_session\nPAM_TTY=ssh\n```\n\n## Installation\n\nDownload the latest release and put it in the `/usr/local/bin/` directory\non the target machine.  You can use any directory you like, so long as you\nchange the PAM configuration to reference the correct installation path.\n\nThe binary is self-contained, all libraries and dependencies are\nstatically-linked.\n\nBefore configuring PAM, you can test that everything is working by running\nthe following command on the server to send a test event:\n\n```\nPAM_TYPE=\"open_session\" PAM_USER=\"test\" PAM_RHOST=\"test\" tattle\n```\n\nMake sure that you have a CloudWatch Event Rule setup or else the event\nwill not be consumed and processed by anything.  The simplest Event Rule\nis to add a target to an SNS topic that sends an email to you.  The\nbroadest event pattern to use when creating the rule is:\n\n```json\n{\n  \"source\": [\n    \"com.unbounce.tattle\"\n  ]\n}\n```\n\n## Failure Conditions\n\nAs this application relies on the distributed nature of AWS, there are several ways in which it can fail.\n\n### Tattle run outside of EC2\n\nThis code requires the use of EC2's metadata service in order to discover\nthe machine's identity.  It cannot be used without being on EC2 and will\nthrow an error.\n\n### Metadata service is unavailable\n\nThe Metadata service could be unavailable due to downtime of the API endpoint, or networking issues with the EC2 instance.  In this event, tattle cannot retrieve the identity document to discover information about itself.\n\n### EC2 has no IAM Role\n\nIt is difficult to know if the EC2 instance has permission to emit events to CloudWatch Events until the request is made.  In this case, tattle will panic and emit an error back to the logs.\n\n```\npanic: Error sending event, EC2RoleRequestError: no EC2 instance role found\ncaused by: EC2MetadataError: failed to make EC2Metadata request\ncaused by: \u003c?xml version=\"1.0\" encoding=\"iso-8859-1\"?\u003e\n\u003c!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"\u003e\n \u003chead\u003e\n  \u003ctitle\u003e404 - Not Found\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n  \u003ch1\u003e404 - Not Found\u003c/h1\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n\n\ngoroutine 1 [running]:\nmain.main()\n        /usr/local/bin/tattle/main.go:72 +0x8db\n```\n\nA panic was chosen so that the caller can easily see where the error is\ncoming from, without custom formatting or interpretation by tattle.  This\nmay change in the future.\n\n## License\n\nMIT License.  See [LICENSE](LICENSE) for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbounce%2Ftattle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funbounce%2Ftattle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbounce%2Ftattle/lists"}