Skip to content

Commit

Permalink
Added support for configurable private networks
Browse files Browse the repository at this point in the history
  • Loading branch information
dekobon committed Sep 6, 2017
1 parent 0fca65b commit 26b6352
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project aims to adhere to [Semantic Versioning](http://semver.org/).

## [0.1.0] - 2017-09-05
### Added
- Added support for configurable private networks

## [0.0.1] - 2017-09-04
### Added
- Initial release
6 changes: 6 additions & 0 deletions example/nic-audit.json5
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
"from" : "triton-nic-audit@some.site",
"subject" : "Illegal Network Configuration Detected"
},
// RFC 1918 networks are defined below - you can add or modify this list
"private_network_blocks" : [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
],
/* nic_groups contains all of the matching patterns to trigger
* an audit alert. */
"nic_groups" : {
Expand Down
8 changes: 5 additions & 3 deletions src/github.com/joyent/nic-audit/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ func processAlerts(alerts list.List, client compute.ComputeClient,
aggregate += fmt.Sprintf(" Instance Networks: %v\n", alert.Instance.Networks)

if len(account.NetworksToRemove) > 0 {
networksRemoved, removeErr := removeNICsBasedOnNetworks(account.NetworksToRemove, alert.Instance, client)
networksRemoved, removeErr := removeNICsBasedOnNetworks(
account.NetworksToRemove, alert.Instance, client,
config.PrivateNetworkBlocks)
if removeErr != nil {
log.Printf("Error removing network for instance [%v]: %v\n",
alert.Instance.ID, removeErr)
Expand All @@ -88,8 +90,8 @@ func processAlerts(alerts list.List, client compute.ComputeClient,

// logAlert outputs a message to STDOUT reporting the specified alert.
func logAlert(alert Alert) {
alertLogger.Printf("%v: %v %v\n", alert.NicGroupName,
alert.Instance.Name, alert.Instance.IPs)
alertLogger.Printf("%v: %v (%v) %v\n", alert.NicGroupName,
alert.Instance.Name, alert.Instance.ID, alert.Instance.IPs)
}

// emailAlerts emails the contents of the specified body text to the
Expand Down
12 changes: 7 additions & 5 deletions src/github.com/joyent/nic-audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func auditAccount(account Account, nicGroups map[string][]string, config Configu
return instancesErr
}

alerts := createAlertsForOffendingNetworks(account, instances, nicGroups)
alerts := createAlertsForOffendingNetworks(account, instances, nicGroups,
config.PrivateNetworkBlocks)
processAlerts(alerts, *client, config)

return nil
Expand Down Expand Up @@ -74,13 +75,14 @@ func setupTritonClient(account Account) (*compute.ComputeClient, error) {
// createAlertsForOffendingNetworks aggregates alerts for every offending
// network pattern match and returns the results as a list.
func createAlertsForOffendingNetworks(account Account, instances []*compute.Instance,
nicGroups map[string][]string) list.List {
nicGroups map[string][]string, privateNetworkBlocks []string) list.List {

alerts := list.New()

for _, instance := range instances {
for nicGroup, networkIds := range nicGroups {
matchingTotal := countMatchingNetworkIds(*instance, networkIds)
matchingTotal := countMatchingNetworkIds(*instance, networkIds,
privateNetworkBlocks)

if matchingTotal == len(networkIds) {
alert := Alert{
Expand All @@ -101,7 +103,7 @@ func createAlertsForOffendingNetworks(account Account, instances []*compute.Inst
// offending network match criteria. Typically, the result of this method
// would be compared to the number of offending networks in the nib_groups
// configuration.
func countMatchingNetworkIds(instance compute.Instance, searchStrings []string) int {
func countMatchingNetworkIds(instance compute.Instance, searchStrings []string, privateNetworkBlocks []string) int {
count := 0

for _, search := range searchStrings {
Expand Down Expand Up @@ -131,7 +133,7 @@ func countMatchingNetworkIds(instance compute.Instance, searchStrings []string)
if search == "public" {
for _, instanceIpString := range instance.IPs {
instanceIp := net.ParseIP(instanceIpString)
if isPublicIP(instanceIp) {
if isPublicIP(instanceIp, privateNetworkBlocks) {
count += 1
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/github.com/joyent/nic-audit/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import (

// Configuration contains all of the configuration values for the application.
type Configuration struct {
EmailAlerts EmailAlerts `json:"email_alerts"`
NicGroups map[string][]string `json:"nic_groups"`
Accounts []Account `json:"accounts"`
EmailAlerts EmailAlerts `json:"email_alerts"`
PrivateNetworkBlocks []string `json:"private_network_blocks"`
NicGroups map[string][]string `json:"nic_groups"`
Accounts []Account `json:"accounts"`
}

// EmailAlerts contains the configuration needed to send an email to alert when
Expand Down
31 changes: 21 additions & 10 deletions src/github.com/joyent/nic-audit/ip_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,33 @@
package main

import (
"fmt"
"log"
"net"
)

// isPrivateIP determines if the specified IP address is a RFC 1918
// isPrivateIP determines if the specified IP address is on a
// private network.
func isPrivateIP(ip net.IP) bool {
_, private24BitBlock, _ := net.ParseCIDR("10.0.0.0/8")
_, private20BitBlock, _ := net.ParseCIDR("172.16.0.0/12")
_, private16BitBlock, _ := net.ParseCIDR("192.168.0.0/16")
return private24BitBlock.Contains(ip) ||
private20BitBlock.Contains(ip) ||
private16BitBlock.Contains(ip)
func isPrivateIP(ip net.IP, privateBlocks []string) bool {
for i := 0; i < len(privateBlocks); i++ {
_, privateBlock, parseErr := net.ParseCIDR(privateBlocks[i])

if parseErr != nil {
msg := fmt.Sprintf("Unable to parse private network [%v]. %v",
privateBlock, parseErr)
log.Fatalln(msg)
}

if privateBlock.Contains(ip) {
return true
}
}

return false
}

// isPublicIP determines if the specified IP address is not a RFC 1918
// private network.
func isPublicIP(ip net.IP) bool {
return !isPrivateIP(ip)
func isPublicIP(ip net.IP, privateBlocks []string) bool {
return !isPrivateIP(ip, privateBlocks)
}
5 changes: 3 additions & 2 deletions src/github.com/joyent/nic-audit/nics.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import (
// removeNICsBasedOnNetworks removes all NICs from the specified instance
// where the NIC connects to one of the specified networks.
func removeNICsBasedOnNetworks(networks []string,
instance compute.Instance, client compute.ComputeClient) ([]string, error) {
instance compute.Instance, client compute.ComputeClient,
privateNetworkBlocks []string) ([]string, error) {

listNICsInput := compute.ListNICsInput{
InstanceID: instance.ID,
Expand Down Expand Up @@ -67,7 +68,7 @@ func removeNICsBasedOnNetworks(networks []string,
// If our "network" is generalized "public" network
if network == "public" {
nicIp := net.ParseIP(nic.IP)
if isPublicIP(nicIp) {
if isPublicIP(nicIp, privateNetworkBlocks) {
macs[macCount] = nic.MAC
networksToRemove[macCount] = network
macCount++
Expand Down

0 comments on commit 26b6352

Please sign in to comment.