mirror of
https://github.com/jessfraz/dockerfiles.git
synced 2024-11-27 04:16:45 +01:00
add k8scan
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
57baab4176
commit
379820c688
31
k8scan/Dockerfile
Normal file
31
k8scan/Dockerfile
Normal file
|
@ -0,0 +1,31 @@
|
|||
FROM golang:alpine as builder
|
||||
MAINTAINER Jessica Frazelle <jess@linux.com>
|
||||
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
ENV GOPATH /go
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates
|
||||
|
||||
COPY main.go /go/src/k8scan/
|
||||
|
||||
RUN set -x \
|
||||
&& apk add --no-cache --virtual .build-deps \
|
||||
git \
|
||||
gcc \
|
||||
libc-dev \
|
||||
libgcc \
|
||||
make \
|
||||
&& cd /go/src/k8scan/ \
|
||||
&& go get -d . \
|
||||
&& CGO_ENABLED=0 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o /usr/bin/k8scan *.go \
|
||||
&& apk del .build-deps \
|
||||
&& rm -rf /go \
|
||||
&& echo "Build complete."
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /usr/bin/k8scan /usr/bin/k8scan
|
||||
COPY --from=builder /etc/ssl/certs/ /etc/ssl/certs
|
||||
|
||||
CMD [ "k8scan" ]
|
181
k8scan/main.go
Normal file
181
k8scan/main.go
Normal file
|
@ -0,0 +1,181 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
cidr = "0.0.0.0/0"
|
||||
beginPort = 80
|
||||
endPort = 65535
|
||||
|
||||
arinAPIEndpoint = "http://whois.arin.net/rest/ip/%s"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// On ^C, or SIGTERM handle exit.
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
signal.Notify(c, syscall.SIGTERM)
|
||||
go func() {
|
||||
for sig := range c {
|
||||
logrus.Infof("Received %s, exiting.", sig.String())
|
||||
os.Exit(0)
|
||||
}
|
||||
}()
|
||||
|
||||
logrus.Infof("Scanning for Kubernetes Dashboards and API Servers on %s over port range %d-%d", cidr, beginPort, endPort)
|
||||
logrus.Infof("This may take a bit...")
|
||||
|
||||
ip, ipnet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
|
||||
wg.Add(1)
|
||||
go func(ip string) {
|
||||
defer wg.Done()
|
||||
|
||||
for port := beginPort; port <= endPort; port++ {
|
||||
// Check if the port is open.
|
||||
ok := portOpen(ip, port)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if it's a kubernetes dashboard.
|
||||
ok = isKubernetesDashboard(ip, port)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s:%d\n", ip, port)
|
||||
// Get the info for the ip address.
|
||||
info, err := getIPInfo(ip)
|
||||
if err != nil {
|
||||
logrus.Warnf("ip info err: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s:%d\t%s\t%s\t%s\n",
|
||||
ip, port,
|
||||
info.Organization.Handle, info.Organization.Name, info.Organization.Reference)
|
||||
}
|
||||
}(ip.String())
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func portOpen(ip string, port int) bool {
|
||||
c, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), 2*time.Second)
|
||||
if err != nil {
|
||||
// logrus.Warnf("listen at %s:%s failed: %v", ip, port, err)
|
||||
return false
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isKubernetesDashboard(ip string, port int) bool {
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 3,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tryAddrs := []string{
|
||||
fmt.Sprintf("http://%s:%d", ip, port),
|
||||
fmt.Sprintf("https://%s:%d", ip, port),
|
||||
fmt.Sprintf("http://%s:%d/api/", ip, port),
|
||||
fmt.Sprintf("https://%s:%d/api/", ip, port),
|
||||
}
|
||||
|
||||
var (
|
||||
resp *http.Response
|
||||
err = errors.New("not yet run")
|
||||
uri string
|
||||
)
|
||||
|
||||
for i := 0; i < len(tryAddrs) && err != nil; i++ {
|
||||
uri = tryAddrs[i]
|
||||
resp, err = client.Get(uri)
|
||||
}
|
||||
if err != nil {
|
||||
//logrus.Warnf("getting %s:%s failed: %v", ip, port, err)
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
body := strings.ToLower(string(b))
|
||||
if strings.Contains(body, "kubernetes") ||
|
||||
(strings.Contains(body, "versions") && strings.Contains(body, "serverAddress")) {
|
||||
logrus.Infof("uri: %s", uri)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type ARINResponse struct {
|
||||
Organization OrganizationJSON `json:"orgReg,omitempty"`
|
||||
}
|
||||
|
||||
type OrganizationJSON struct {
|
||||
Handle string `json:"@handle,omitempty"`
|
||||
Name string `json:"@name,omitempty"`
|
||||
Reference string `json:"$,omitempty"`
|
||||
}
|
||||
|
||||
func getIPInfo(ip string) (b ARINResponse, err error) {
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(arinAPIEndpoint, ip), nil)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func inc(ip net.IP) {
|
||||
for j := len(ip) - 1; j >= 0; j-- {
|
||||
ip[j]++
|
||||
if ip[j] > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user