Skip to content

Commit

Permalink
Code re-organization; provide new rules option to print them out
Browse files Browse the repository at this point in the history
  • Loading branch information
vkuznet committed Jun 26, 2024
1 parent e4ffe8e commit 0cbf08d
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 130 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,26 @@ auth-proxy-server -config config.json
# to run with x509 authentication
auth-proxy-server -config config.json -useX509
```

### Code organization
The code is implemented as the following modules:
- [config.go](config.go) provides server configuration methods
- [cric.go](cric/cric.go) provides CMS CRIC service functionality
- [data.go](data.go) holds all data structures used in the package
- [logging.go](logging/logging.go) provides logging functionality
- [oauth.go](oauth.go) provides implementation of oathProxyServer
- [redirect.go](redirect.go) provides logic of reverse proxy
- [server.go](server.go) provides main APS server logic
- [utils.go](utils.go) provides various utils used in a code
- [x509.go](x509.go) provides implementation of x509ProxyServer

Both server implementations (oauthProxyServer and x509ProxyServer) support
/server end-point which can be used to update server settings, e.g.
curl -X POST -H"Content-type: application/json" -d '{"verbose":true}' https://a.b.com/server

This codebase is based on different examples taken from:
- [Reverse proxy server in one line](https://hackernoon.com/writing-a-reverse-proxy-in-just-one-line-with-go-c1edfa78c84b)
- [Reverse proxy server demo](https://github.com/bechurch/reverse-proxy-demo/blob/master/main.go)
- [Reverse proxy server](https://imti.co/golang-reverse-proxy/)
- [Metrics in reverse proxy server](https://itnext.io/capturing-metrics-with-gos-reverse-proxy-5c36cb20cb20)
- [GoLang reverse proxy](https://www.integralist.co.uk/posts/golang-reverse-proxy/)
131 changes: 3 additions & 128 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,17 @@ package main
// Copyright (c) 2020 - Valentin Kuznetsov <[email protected]>
//

/*
The code is implemented as the following modules:
- config.go provides server configuration methods
- cric.go provides CMS CRIC service functionality
- data.go holds all data structures used in the package
- logging.go provides logging functionality
- oauth.go provides implementation of oathProxyServer
- x509.go provides implementation of x509ProxyServer
- utils.go provides various utils used in a code
Both server implementations (oauthProxyServer and x509ProxyServer) support
/server end-point which can be used to update server settings, e.g.
curl -X POST -H"Content-type: application/json" -d '{"verbose":true}' https://a.b.com/server
This codebase is based on different examples taken from:
https://hackernoon.com/writing-a-reverse-proxy-in-just-one-line-with-go-c1edfa78c84b
https://github.com/bechurch/reverse-proxy-demo/blob/master/main.go
https://imti.co/golang-reverse-proxy/
https://itnext.io/capturing-metrics-with-gos-reverse-proxy-5c36cb20cb20
https://www.integralist.co.uk/posts/golang-reverse-proxy/
*/

import (
"flag"
"fmt"
"log"
"os"
"runtime"
"time"

_ "expvar" // to be used for monitoring, see https://github.com/divan/expvarmon
_ "net/http/pprof" // profiler, see https://golang.org/pkg/net/http/pprof/

"github.com/dmwm/cmsauth"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/shirou/gopsutil/cpu"
"github.com/vkuznet/auth-proxy-server/auth"
"github.com/vkuznet/auth-proxy-server/cric"
"github.com/vkuznet/auth-proxy-server/logging"
)

// StartTime of the server
var StartTime time.Time

// NumPhysicalCores represents number of cores in our node
var NumPhysicalCores int

// NumLogicalCores represents number of cores in our node
var NumLogicalCores int

// CMSAuth structure to create CMS Auth headers
var CMSAuth cmsauth.CMSAuth

// gitVersion of the code shows git hash
var gitVersion string

Expand All @@ -85,97 +43,14 @@ func main() {
flag.BoolVar(&useX509, "useX509", false, "start X509 auth server")
var scitokens bool
flag.BoolVar(&scitokens, "scitokens", false, "start scitokens server")
var rules bool
flag.BoolVar(&rules, "rules", false, "print APS redirect rules")
var version bool
flag.BoolVar(&version, "version", false, "print version information about the server")
flag.Parse()
if version {
fmt.Println(info())
os.Exit(0)
}
err := parseConfig(config)
if err != nil {
log.Fatalf("unable to parse config %s, error %v\n", config, err)
}

// configure logger with log time, filename, and line number
log.SetFlags(0)
if Config.Verbose > 0 {
log.SetFlags(log.Lshortfile)
}
log.SetOutput(new(logging.LogWriter))
if Config.LogFile != "" {
rl, err := rotatelogs.New(LogName())
if err == nil {
rotlogs := logging.RotateLogWriter{RotateLogs: rl}
log.SetOutput(rotlogs)
}
}
// initialize logging module
logging.CMSMonitType = Config.MonitType
logging.CMSMonitProducer = Config.MonitProducer

if port > 0 {
log.Println("overwrite server port number to", port)
Config.Port = port
}
if metricsPort > 0 {
log.Println("overwrite server metrics port number to", metricsPort)
Config.MetricsPort = metricsPort
}
if logFile != "" {
log.Println("overwrite server log file to", logFile)
Config.LogFile = logFile
}
if Config.Verbose > 0 {
log.Printf("%+v\n", Config.String())
}

// read RootCAs once
_rootCAs = RootCAs()

// initialize ingress rules only once
_ingressMap, _ingressRules = readIngressRules()

// setup StartTime and metrics last update time
StartTime = time.Now()
MetricsLastUpdateTime = time.Now()
NumPhysicalCores, err = cpu.Counts(false)
if err != nil {
log.Printf("unable to get number of physical cores, error %v\n", err)
NumPhysicalCores = 0
}
NumLogicalCores, err = cpu.Counts(true)
if err != nil {
log.Printf("unable to get number of logical cores, error %v\n", err)
NumLogicalCores = 0
}

// initialize all particiapted providers
auth.Init(Config.Providers, Config.Verbose)

// initialize cmsauth module
CMSAuth.Init(Config.Hmac)

// start our servers
if useX509 {
if Config.CricURL != "" || Config.CricFile != "" {
go cric.UpdateCricRecords("dn", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
x509ProxyServer()
return
} else if scitokens {
if Config.CricURL != "" || Config.CricFile != "" {
go cric.UpdateCricRecords("dn", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
scitokensServer()
return
}
if Config.CricURL != "" || Config.CricFile != "" {
// Get CRIC records
go cric.UpdateCricRecords("id", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
// Get AIM records
go getIAMInfo()
// start OAuth server
oauthProxyServer()
Server(config, port, metricsPort, logFile, useX509, scitokens, rules)
}
38 changes: 36 additions & 2 deletions redirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"net/url"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -158,6 +159,29 @@ func srvURL(surl string) string {
return surl
}

// helper function to print APS redirect rules from given config
func printRules() {
var rmap map[string]Ingress
var rules []string
if len(Config.IngressFiles) > 0 {
rmap, rules = RedirectRulesFromFiles(Config.IngressFiles)
} else {
rmap, rules = RedirectRules(Config.Ingress)
}
sort.Strings(rules)
var maxLen int
for _, r := range rules {
if len(r) > maxLen {
maxLen = len(r)
}
}
for _, r := range rules {
if rule, ok := rmap[r]; ok {
fmt.Println(redirectRule(rule, maxLen))
}
}
}

// helper function to read ingress rules
func readIngressRules() (map[string]Ingress, []string) {
var rmap map[string]Ingress
Expand All @@ -168,16 +192,26 @@ func readIngressRules() (map[string]Ingress, []string) {
rmap, rules = RedirectRules(Config.Ingress)
}
if Config.Verbose > 0 {
sort.Strings(rules)
var maxLen int
for _, r := range rules {
if len(r) > maxLen {
maxLen = len(r)
}
}
log.Println("ingress paths", rules)
for _, item := range rmap {
log.Println(redirectRule(item))
log.Println(redirectRule(item, maxLen))
}
}
return rmap, rules
}

// helper function to print human readable redirect rule
func redirectRule(r Ingress) string {
func redirectRule(r Ingress, maxLen int) string {
for i := len(r.Path); i < maxLen; i++ {
r.Path += " "
}
out := fmt.Sprintf("%s => %s/%s", r.Path, r.ServiceURL, r.NewPath)
if strings.HasPrefix(r.NewPath, "/") {
out = fmt.Sprintf("%s => %s%s", r.Path, r.ServiceURL, r.NewPath)
Expand Down
119 changes: 119 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package main

import (
"log"
"time"

"github.com/dmwm/cmsauth"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/shirou/gopsutil/cpu"
"github.com/vkuznet/auth-proxy-server/auth"
"github.com/vkuznet/auth-proxy-server/cric"
"github.com/vkuznet/auth-proxy-server/logging"
)

// StartTime of the server
var StartTime time.Time

// NumPhysicalCores represents number of cores in our node
var NumPhysicalCores int

// NumLogicalCores represents number of cores in our node
var NumLogicalCores int

// CMSAuth structure to create CMS Auth headers
var CMSAuth cmsauth.CMSAuth

// Server starts APS server
func Server(config string, port, metricsPort int, logFile string, useX509, scitokens, rules bool) {
err := parseConfig(config)
if err != nil {
log.Fatalf("unable to parse config %s, error %v\n", config, err)
}
if rules {
printRules()
return
}

// configure logger with log time, filename, and line number
log.SetFlags(0)
if Config.Verbose > 0 {
log.SetFlags(log.Lshortfile)
}
log.SetOutput(new(logging.LogWriter))
if Config.LogFile != "" {
rl, err := rotatelogs.New(LogName())
if err == nil {
rotlogs := logging.RotateLogWriter{RotateLogs: rl}
log.SetOutput(rotlogs)
}
}
// initialize logging module
logging.CMSMonitType = Config.MonitType
logging.CMSMonitProducer = Config.MonitProducer

if port > 0 {
log.Println("overwrite server port number to", port)
Config.Port = port
}
if metricsPort > 0 {
log.Println("overwrite server metrics port number to", metricsPort)
Config.MetricsPort = metricsPort
}
if logFile != "" {
log.Println("overwrite server log file to", logFile)
Config.LogFile = logFile
}
if Config.Verbose > 0 {
log.Printf("%+v\n", Config.String())
}

// read RootCAs once
_rootCAs = RootCAs()

// initialize ingress rules only once
_ingressMap, _ingressRules = readIngressRules()

// setup StartTime and metrics last update time
StartTime = time.Now()
MetricsLastUpdateTime = time.Now()
NumPhysicalCores, err = cpu.Counts(false)
if err != nil {
log.Printf("unable to get number of physical cores, error %v\n", err)
NumPhysicalCores = 0
}
NumLogicalCores, err = cpu.Counts(true)
if err != nil {
log.Printf("unable to get number of logical cores, error %v\n", err)
NumLogicalCores = 0
}

// initialize all particiapted providers
auth.Init(Config.Providers, Config.Verbose)

// initialize cmsauth module
CMSAuth.Init(Config.Hmac)

// start our servers
if useX509 {
if Config.CricURL != "" || Config.CricFile != "" {
go cric.UpdateCricRecords("dn", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
x509ProxyServer()
return
} else if scitokens {
if Config.CricURL != "" || Config.CricFile != "" {
go cric.UpdateCricRecords("dn", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
scitokensServer()
return
}
if Config.CricURL != "" || Config.CricFile != "" {
// Get CRIC records
go cric.UpdateCricRecords("id", Config.CricFile, Config.CricURL, Config.UpdateCricInterval, Config.CricVerbose)
}
// Get AIM records
go getIAMInfo()
// start OAuth server
oauthProxyServer()
}

0 comments on commit 0cbf08d

Please sign in to comment.