---
title: "Log SSH logins"
description: "Record SSH logins on your nodes as Guardian events."
product: "Guardian"
edition: "Classic"
type: "workflow"
url: "https://docs.cloudhouse.com/guardian/classic/tech-articles/log-ssh-logins/"
---
# Log SSH logins

Guardian's events functionality provides a rich timeline of appliance events such as nodes being scanned successfully, policy failures or user logins. During debugging or crisis resolution these time-based events can be beneficial to discover the root cause of a problem. Augmenting the inbuilt events with external events can greatly improve the amount of information available when diagnosing an issue. This guide describes a walkthrough of how to inject an event into the Guardian event stream when a user logs into a machine via SSH. For context, a current Guardian user wants to log our support Engineers logging into the Guardian appliance itself, for their own internal security policies.

Applies to: `Guardian Classic`

## Overview

Here we are going to:

- Construct an API call that will log a `ssh_login` event to the Events stream.
- Add this API call to as a SSH login hook.
- Create an Event View in Guardian to display SSH login events.

## Create the API call

Here we are going to create a Ruby script that can post an event to the Event stream, but you could also use Python, cURL or some other method to post to the API.

### Ruby example

```
require 'httparty'

api_key = "1234"
api_sec = "5678"
hostname = "https://my-hostname.cloudhouse.com"

response = HTTParty.post("#{hostname}/api/v2/events.json",
                         :headers => {
               'Authorization' => "Token token=\"#{api_key}#{api_sec}\""
             },
             :body => {
               :variables => {"type" => "ssh_login"}
             })
puts response.code
puts response.body
```

### curl example

```
#!/bin/bash

API_KEY="1234"
API_SEC="5678"

curl -v -X POST -d 'variables={"type":"ssh_login"}' \
-H "Authorization: Token token=\"$API_KEY$API_SEC\"" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
https://my-hostname.cloudhouse.com/api/v2/events.json
```

### Python SDK example

```
# pip install upguard
import upguard

api_key = "1234"
sec_key = "5678"

o = upguard.Account("https://me.cloudhouse.com", api_key, sec_key)

ext = o.new_external_event()
ext.type = "ssh_login"
ext.variables["key"] = "value"
ext.variables["number"] = 123
ext.create()
```

Here we are calling the `/api/v2/events` endpoint to log the event. The only required part of the body is a `variables` parameter with a JSON object with a key called `type`. See [Events - Create](https://core-api.cloudhouse.com/#tag/Events/operation/eventsCreateV2) for more information about this API endpoint.

You can find the API Key and API Secret by accessing Manage Accounts in the top-right menu, then clicking on the name of our Account to display the Service API Key and Secret Key. Substitute your appliance's hostname into the `hostname` variable.

## A slightly more secure API caller

You could also bake the URL, API key and secret of your appliance account into a binary file that just posts this event type to your instance. The following `golang` code can be compiled into a "binary builder" executable that can then, in turn, be instructed to build an event posting binary that contains your credentials stored internally.

Copy and paste the following code into a file in your `$GOPATH/src` folder structure into a file called `main.go`.

### GoLang example

```
package main

import (
  "bytes"
  "flag"
  "fmt"
  "os"
)

type Buf struct{
  buffer bytes.Buffer
}

func (self *Buf) W(format string, args ...interface{}) {
  self.buffer.WriteString(fmt.Sprintf(format, args...))
  self.buffer.WriteString("\n")
}

func (self *Buf) String() string {
  return self.buffer.String()
}

func main() {
  url := flag.String("url", "", "The base URL of your appliance, e.g. https://you.cloudhouse.com")
  key := flag.String("key", "", "The API Key")
  sec := flag.String("sec", "", "The API Secret Key")
  flag.Parse()

  if *url == "" {
    fmt.Println("Missing -url param")
    os.Exit(1)
  }
  if *key == "" {
    fmt.Println("Missing -key param")
    os.Exit(1)
  }
  if *sec == "" {
    fmt.Println("Missing -sec param")
    os.Exit(1)
  }

  var b Buf

  b.W("package main")
  b.W("")
  b.W("import (")
  b.W("  \"bytes\"")
  b.W("  \"fmt\"")
  b.W("  \"io/ioutil\"")
  b.W("  \"net/http\"")
  b.W(")")
  b.W("")
  b.W("func die(err error) {")
  b.W("  if err != nil {")
  b.W("    panic(err)")
  b.W("  }")
  b.W("}")
  b.W("")
  b.W("func main() {")
  b.W("  payload := \"variables={\\\"type\\\":\\\"ssh_login\\\"}\"")
  b.W("  client := &http.Client{}")
  b.W("  req, err := http.NewRequest(\"POST\", \"%s/api/v2/events.json\", bytes.NewBuffer([]byte(payload)))", *url)
  b.W("  die(err)")
  b.W("  req.Header.Set(\"Authorization\", \"Token token=\\\"%s%s\\\"\")", *key, *sec)
  b.W("  req.Header.Set(\"Accept\", \"application/json\")")
  b.W("  res, err := client.Do(req)")
  b.W("  die(err)")
  b.W("  fmt.Printf(\"res.Code: %%v\\n\", res.StatusCode)")
  b.W("  content, err := ioutil.ReadAll(res.Body)")
  b.W("  die(err)")
  b.W("  fmt.Printf(\"res.Body: %%v\\n\", string(content))")
  b.W("}")

  fmt.Print(b.String())
}
```

Next, run the code with the help option to see which parameters you can specify.

```
$ go run main.go -h
Usage:
-key string
    The API Key
-sec string
    The API Secret Key
-url string
    The base URL of your appliance, e.g. https://you.cloudhouse.com
```

Running this file with the correct `key`, `sec`, and `url` parameters will generate the source of a go file that is able to post an `ssh_login` event to your appliance with these details baked in.

!!! note

    The baked in credentials can still be extracted from the binary file by using the "strings" command. If you require an even more secure approach, please contact Guardian Support.

Create the binary file by running the following commands:

```
$ mkdir -p out
$ go run main.go -key 1234 -sec 5678 -url https://you.cloudhouse.com > out/main.go
$ cd out
$ go build -installsuffix 'static' -o log_ssh_logins.out .
$ # test that it worked
$ ./log_ssh_logins.out
... should print HTTP response code and body from API ...
```

## Install the login hook

There are many options to execute a command when, for example, all users log into a machine, or when a particular user logs into a machine. For this use case, we're just going to add the execution of this script to the user's `~/.bashrc` file. You could also add this to a user's `~/.bash_profile` depending on your OS.

I have added this line to the bottom of my `~/.bashrc`:

### Ruby

```
ruby /home/username/util/log-when-i-log-in.rb
```

### Golang

```
/home/user/util/log_ssh_logins.out
```

## View logged events

Navigate to the **Events** tab (**Control** > **Events**) and search with the following query:

```
type=External Event AND variables.type=ssh_login
```

This should display all events that have been externally logged by this particular external event. If you want to log multiple login attempts from different machines you could either use a more specific `variables.type` value in the posting script, or add extra variables to query on.

## What next?

It is a good idea to log every login to a machine via SSH for audit purposes, but it is also a good idea to be notified when this happens in case there are any unwanted login attempts that successfully gain access to a machine.

See [Events](https://docs.cloudhouse.com/guardian/classic/control/events/events/index.md) for more information on how to create a permanent view from this query, and how to add an action when an event of this type occurs, such as sending an email to the Ops team, or posting a message to your favourite chat client.
