Skip to content

Commit

Permalink
Merge pull request #58 from natron-io/feature/#57
Browse files Browse the repository at this point in the history
add slack notification route on broadcast channel messages and fix au…
  • Loading branch information
janlauber authored Feb 5, 2022
2 parents bf7389f + 6a41754 commit 666a878
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 37 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ You can add `<tenant name>` in front of the path to get the tenant specific data
`/login/github` - Login with GitHub \
`/login/github/callback` - Callback after GitHub login

#### notifications
`/api/v1/notifications` - Get the Slack notification messages of the broadcast channel provided via envs

##### general tenant resources
`/api/v1/pods` - Get pods of a tenant \
`/api/v1/namespaces` - Get namespaces of a tenant \
Expand Down Expand Up @@ -63,6 +66,10 @@ You can send the github code with json body `{"github_code": "..."}` to the `/lo
### auth
`SECRET_KEY` - JWT secret key *optional* (default: random 32 bytes, displayed in the logs)

### notifications
`SLACK_TOKEN` - Tenant API Slack Application User Token (if not set, the notification REST route will be deactivated) \
`SLACK_BROADCAST_CHANNEL_ID` - BroadCast Slack Channel ID

### tenant ressource identifiers
`TENANT_LABEL` - label key for selecting tenant ressources *optional* (default: "natron.io/tenant")

Expand Down
10 changes: 6 additions & 4 deletions controllers/authController.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,8 @@ func CheckAuth(c *fiber.Ctx) []string {
return nil
}

// parse token with secret key
token, _ = jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
_, ok := token.Method.(*jwt.SigningMethodHMAC)
if !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(util.SECRET_KEY), nil
})

Expand Down Expand Up @@ -165,5 +162,10 @@ func CheckAuth(c *fiber.Ctx) []string {
githubTeamSlugs = append(githubTeamSlugs, githubTeam.(string))
}

if githubTeamSlugs == nil {
util.WarningLogger.Printf("IP %s is not authorized", c.IP())
return nil
}

return githubTeamSlugs
}
20 changes: 8 additions & 12 deletions controllers/costController.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ func GetCPUCostSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -52,9 +51,8 @@ func GetMemoryCostSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -93,9 +91,8 @@ func GetStorageCostSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -150,9 +147,8 @@ func GetIngressCostSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down
52 changes: 52 additions & 0 deletions controllers/notificationController.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package controllers

import (
"github.com/gofiber/fiber/v2"
"github.com/natron-io/tenant-api/util"
"github.com/slack-go/slack"
)

// GetNotifications returns all slack notifications of a broadcast channel by authenticated users tenants
func GetNotifications(c *fiber.Ctx) error {

util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())

tenants := CheckAuth(c)
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}

// set authorization header Bearer token as util.SLACK_TOKEN
if util.SLACK_TOKEN == "" {
return c.Status(500).JSON(fiber.Map{
"message": "Internal Server Error",
})
}

historyParams := slack.GetConversationHistoryParameters{
ChannelID: util.BroadCastChannelID,
Limit: 10,
}

// make slack api call to get all notifications of the BroadCast channel
resp, err := util.SlackClient.GetConversationHistory(&historyParams)

// parse messages to string slice
var notifications []string
for _, message := range resp.Messages {
if message.Blocks.BlockSet != nil {
notifications = append(notifications, message.Text)
}
}

if err != nil {
util.ErrorLogger.Printf("Error getting slack messages: %v", err)
return c.Status(500).JSON(fiber.Map{
"message": "Internal Server Error",
})
}

return c.JSON(notifications)
}
35 changes: 14 additions & 21 deletions controllers/tenantController.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ func GetPods(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -67,9 +66,8 @@ func GetNamespaces(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -108,9 +106,8 @@ func GetServiceAccounts(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -149,9 +146,8 @@ func GetCPURequestsSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -182,9 +178,8 @@ func GetMemoryRequestsSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -215,9 +210,8 @@ func GetStorageRequestsSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down Expand Up @@ -248,9 +242,8 @@ func GetIngressRequestsSum(c *fiber.Ctx) error {
util.InfoLogger.Printf("%s %s %s", c.IP(), c.Method(), c.Path())
tenant := c.Params("tenant")
tenants := CheckAuth(c)
util.WarningLogger.Printf("tenant: %s", tenant)
if tenants == nil {
c.Status(401).JSON(fiber.Map{
if len(tenants) == 0 {
return c.Status(401).JSON(fiber.Map{
"message": "Unauthorized",
})
}
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/klauspost/compress v1.13.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/slack-go/slack v0.10.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.31.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.24.0 h1:18rpLoQMJBVlLtX/PwgHj3hIxPSeWfN1YeDJ2lEnzjU=
github.com/gofiber/fiber/v2 v2.24.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ=
Expand Down Expand Up @@ -193,6 +194,7 @@ github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
Expand Down Expand Up @@ -280,7 +282,9 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -293,6 +297,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/slack-go/slack v0.10.1 h1:BGbxa0kMsGEvLOEoZmYs8T1wWfoZXwmQFBb6FgYCXUA=
github.com/slack-go/slack v0.10.1/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
Expand Down
6 changes: 6 additions & 0 deletions routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package routes
import (
"github.com/gofiber/fiber/v2"
"github.com/natron-io/tenant-api/controllers"
"github.com/natron-io/tenant-api/util"
"k8s.io/client-go/kubernetes"
)

Expand All @@ -17,6 +18,11 @@ func Setup(app *fiber.App, clientset *kubernetes.Clientset) {
api := app.Group("/api")
v1 := api.Group("/v1")

// Notifications
if util.SLACK_TOKEN != "" {
v1.Get("/notifications", controllers.GetNotifications)
}

// Tenants
v1.Get("/tenants", controllers.GetTenants)

Expand Down
5 changes: 5 additions & 0 deletions tenant-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gofiber/template/html"
"github.com/natron-io/tenant-api/routes"
"github.com/natron-io/tenant-api/util"
"github.com/slack-go/slack"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -61,6 +62,10 @@ func main() {

engine := html.New("./views", ".html")

if util.SLACK_TOKEN != "" {
util.SlackClient = slack.New(util.SLACK_TOKEN)
}

app := fiber.New(fiber.Config{
Views: engine,
})
Expand Down
10 changes: 10 additions & 0 deletions util/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ func LoadEnv() error {
InfoLogger.Printf("MEMORY_COST set using env: %f", MEMORY_COST)
}

if SLACK_TOKEN = os.Getenv("SLACK_TOKEN"); SLACK_TOKEN == "" {
WarningLogger.Println("SLACK_TOKEN is not set")
SLACK_TOKEN = ""
}

if BroadCastChannelID = os.Getenv("SLACK_BROADCAST_CHANNEL_ID"); BroadCastChannelID == "" {
WarningLogger.Println("SLACK_BROADCAST_CHANNEL_ID is not set")
BroadCastChannelID = ""
}

// get every env variable starting with STORAGE_COST_ and parse it to STORAGE_COST with the storage class name after STORAGE_COST_ as key
tempStorageCost := make(map[string]map[string]float64)
for _, env := range os.Environ() {
Expand Down
13 changes: 13 additions & 0 deletions util/slack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package util

import (
"os"

"github.com/slack-go/slack"
)

var (
SLACK_TOKEN = os.Getenv("SLACK_TOKEN")
SlackClient *slack.Client
BroadCastChannelID string
)

0 comments on commit 666a878

Please sign in to comment.