Compare commits
10 Commits
hexadecima
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
0cd721909b | ||
|
315aa55ab7 | ||
|
4d180a1212 | ||
|
3c420dc3db | ||
|
54b52273da | ||
|
93fd6f916b | ||
|
8e2f4e3db8 | ||
|
bb77957ed4 | ||
|
a46c855960 | ||
|
0ea14fd132 |
55
Questions_Answers.md
Normal file
55
Questions_Answers.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
## Level 1 Questions
|
||||||
|
1. How would you prove the code is correct?
|
||||||
|
|
||||||
|
To prove the code is correct I suppose I could set up a test environment
|
||||||
|
where I could account for all connections and run tests like
|
||||||
|
ssh connections, dhclient or dig (dns) connections, nmap port
|
||||||
|
scans, and then ensure the connections I expect from the tests
|
||||||
|
appear in the program's output.
|
||||||
|
|
||||||
|
2. How would you make this solution better?
|
||||||
|
|
||||||
|
I'd improve the solution by making the functions more focused on
|
||||||
|
specific tasks, improving how I present the interface of each
|
||||||
|
function to each other to more specifically eliminate type
|
||||||
|
or value errors. I'd also allot more time to complete the task
|
||||||
|
since I wasn't able to find enough before the deadline.
|
||||||
|
3. Is it possible for this program to miss a connection?
|
||||||
|
|
||||||
|
Yes, if the connection is brief enough so as not to last more than 10
|
||||||
|
seconds and thereby be missed by the most recent read of the
|
||||||
|
/proc/net/tcp file
|
||||||
|
4. If you weren't following these requirements, how would you solve the problem of logging every new connection?
|
||||||
|
|
||||||
|
I would likely find a solution that leverages inotify to detect any change to the file and then read it,
|
||||||
|
rather than polling it every 10 seconds.
|
||||||
|
|
||||||
|
## Level 2 Questions
|
||||||
|
1. Why did you choose 'x' to write the build automation?
|
||||||
|
|
||||||
|
I would simply choose bash, as it's what I'm most familiar with and it
|
||||||
|
can reliably use the go build tools as well as invoke testing
|
||||||
|
systems like kvm/qemu, docker/podman and the like.
|
||||||
|
2. Is there anything else you would test if you had more time?
|
||||||
|
|
||||||
|
If I had more time I'd spend it fleshing out my testing as outlined above
|
||||||
|
and doing a more thorough job of structuring my data in the way
|
||||||
|
that I've modeled it in my head - the choice of go definitely
|
||||||
|
consigned me to reading more than writing with the little time
|
||||||
|
I had. Should have gone with bash I think.
|
||||||
|
3. What is the most important tool, script, or technique you have for solving
|
||||||
|
problems in production? Explain why this tool/script/technique is the most important.
|
||||||
|
|
||||||
|
|
||||||
|
## Level 3 Questions
|
||||||
|
|
||||||
|
1. If you had to deploy this program to hundreds of servers, what would be your
|
||||||
|
preferred method and why?
|
||||||
|
|
||||||
|
I would use ansible and use git to clone, build, and install the script.
|
||||||
|
This method is my preferred one because it's simple to
|
||||||
|
troubleshoot in the event that I run into issues and
|
||||||
|
ansible doesn't require a central orchestrator node. It's
|
||||||
|
also the Infrastructure-as-code tool I'm most familiar with.
|
||||||
|
2. What is the hardest technical problem or outage you've had to solve in your
|
||||||
|
career? Explain what made it so difficult?
|
24
README
Normal file
24
README
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# teleport_devops_challenge
|
||||||
|
|
||||||
|
WARNING: This program is in an incomplete state and does not build successfully.
|
||||||
|
The latest commit that builds successfully can be found here:
|
||||||
|
https://git.libre.audio/seasharp/teleport_devops_challenge/commit/93fd6f916bc5a6b7504c5475f7cbcebabaae5277
|
||||||
|
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- golang 'encoding' package
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Ensure your $GOPATH is set correctly and run:
|
||||||
|
|
||||||
|
1. Execute `go build main.go` in repository root
|
||||||
|
2. Execute `go install teleport_devops_challenge`
|
||||||
|
|
||||||
|
## Executing
|
||||||
|
|
||||||
|
Ensure GOPATH/bin (GOPATH = `go env GOPATH`) has been added to your shell $PATH
|
||||||
|
or execute the following:
|
||||||
|
|
||||||
|
`PATH=/home/$(whoami)/go/bin:$PATH teleport_devops_challenge`
|
52
main.go
52
main.go
@ -1,5 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
|
//"./timer"
|
||||||
|
"time"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -8,7 +12,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
var tcp_data string = read_tcp_file("/proc/net/tcp")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
var loops int = 0
|
||||||
// How to split on space-delimited fields, then colon-delimited fields?
|
// How to split on space-delimited fields, then colon-delimited fields?
|
||||||
// How to turn this byte into a string?
|
// How to turn this byte into a string?
|
||||||
|
|
||||||
@ -16,7 +23,28 @@ func main() {
|
|||||||
// and then converted byte by byte (2 char at a time)
|
// and then converted byte by byte (2 char at a time)
|
||||||
//fmt.Println(convert_address(reverse_string(reverse_bytes("0100007F"))))
|
//fmt.Println(convert_address(reverse_string(reverse_bytes("0100007F"))))
|
||||||
|
|
||||||
tcp_rows(read_tcp_file("/proc/net/tcp"))
|
for _ = range time.Tick(10 * time.Second) {
|
||||||
|
fmt.Println("Waiting 10 seconds...")
|
||||||
|
for num, row := range get_tcp_rows(tcp_data) {
|
||||||
|
row_type := reflect.TypeOf(row)
|
||||||
|
fmt.Println(num, " ", row_type)
|
||||||
|
}
|
||||||
|
// if loops modulo 6 (1min) then
|
||||||
|
// for address in address_list do
|
||||||
|
// if (grep address address_list | wc -l >=3) then
|
||||||
|
// This is a port scan!
|
||||||
|
// fi
|
||||||
|
// done
|
||||||
|
// elseif (wc -l old_tcp_file < wc -l tcp_file) then
|
||||||
|
// for i in (wc -l tcp_file - wc -l old_tcp_flle) do
|
||||||
|
// print New Connection! reverse_strng(reverse_bytes(tcp_file[i])) // This oversimplifies row value selection for the sake
|
||||||
|
// // of pseudocode
|
||||||
|
// done
|
||||||
|
// else
|
||||||
|
// "No new connections. Waiting another 10 seconds..."
|
||||||
|
// fi
|
||||||
|
loops++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(e error) {
|
func check(e error) {
|
||||||
@ -25,17 +53,21 @@ func check(e error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tcp_rows(connections_file string) {
|
// Aiming for an array of [string]string maps
|
||||||
regexpression := regexp.MustCompile(`[^a-zA-Z0-9\r\n\t\v]+`)
|
// Am I looking for a map[string]interface here?
|
||||||
tcp_lines := strings.Split(connections_file, "\n")
|
func get_tcp_rows(connections_file string) []string {
|
||||||
|
tcp_lines := strings.Split(connections_file, "\n")
|
||||||
|
regexpression := regexp.MustCompile(`[\r\n\t\f\v]+`)
|
||||||
|
tcp_columns := regexpression.Split(tcp_lines[0], -1)
|
||||||
|
var tcp_values map[string]string
|
||||||
|
|
||||||
for _, line := range tcp_lines {
|
for i, line := range tcp_lines[1:] {
|
||||||
trim_line := strings.TrimSpace(line)
|
trim_line := strings.TrimSpace(line)
|
||||||
values := regexpression.ReplaceAllString(trim_line, ",")
|
values := regexpression.Split(trim_line, -1)
|
||||||
// Debug
|
column := tcp_columns[i]
|
||||||
// fmt.Println("New Line ==========")
|
tcp_values[column] = values
|
||||||
fmt.Println(values)
|
|
||||||
}
|
}
|
||||||
|
return tcp_values
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a string, create a rune slice, and use a loop to reverse it character-wise.
|
// Take a string, create a rune slice, and use a loop to reverse it character-wise.
|
||||||
|
35
timer/timer.go
Normal file
35
timer/timer.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package timer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
//"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(duration_int int, unit string) *time.Timer {
|
||||||
|
|
||||||
|
start := time.NewTimer(0)
|
||||||
|
duration := time.Duration(duration_int)
|
||||||
|
// fmt.Println(reflect.TypeOf(duration))
|
||||||
|
// timer_10s := time.NewTimer(10 * time.Second)
|
||||||
|
// timer_1m := time.NewTimer(1 * time.Minute)
|
||||||
|
fmt.Println("Duration: ", duration_int, "Unit: ", unit, ".")
|
||||||
|
if unit == "Second" {
|
||||||
|
start = time.NewTimer(duration * time.Second)
|
||||||
|
} else if unit == "Minute" {
|
||||||
|
start = time.NewTimer(duration * time.Minute)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Unit not recognized.")
|
||||||
|
}
|
||||||
|
fmt.Println("Waiting ", duration_int, " ", unit, ".")
|
||||||
|
if start.Stop() {
|
||||||
|
<-start.C
|
||||||
|
fmt.Println("Done waiting ", duration_int, " ", unit, "!")
|
||||||
|
}
|
||||||
|
return start
|
||||||
|
// for elapsed < ten_seconds {
|
||||||
|
//}
|
||||||
|
// for
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reset
|
Loading…
Reference in New Issue
Block a user