Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use auth middleware for LB #74

Merged
merged 2 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ run.sh
*.db
*.prof
lasttimestamp
!pkg/lb/testdata/ceems_api_server.db

# Ignore promu related files
promu*
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ test-e2e: $(PROMTOOL) build pkg/collector/testdata/sys/.unpacked pkg/collector/t
./scripts/e2e-test.sh -s api-global-usage-admin-query
./scripts/e2e-test.sh -s api-current-usage-admin-denied-query
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-forbid-user-query
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-allow-user-query
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-allow-admin-query
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-auth
endif

Expand Down Expand Up @@ -182,6 +185,9 @@ test-e2e-update: $(PROMTOOL) build pkg/collector/testdata/sys/.unpacked pkg/coll
./scripts/e2e-test.sh -s api-global-usage-admin-query -u || true
./scripts/e2e-test.sh -s api-current-usage-admin-denied-query -u || true
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb -u || true
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-forbid-user-query -u || true
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-allow-user-query -u || true
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-allow-admin-query -u || true
@env GOBIN=$(FIRST_GOPATH) ./scripts/e2e-test.sh -s lb-auth -u || true
endif

Expand Down
30 changes: 30 additions & 0 deletions build/package/ceems_lb/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@ strategy: resource-based
# proxy request to backend or not.
# db_path: /var/lib/ceems_api_server/ceems_api_server.db

# List of admin users.
# Requests from users defined in this list will be passed through without
# any additional checks. This allows admin users to be able to access
# dashboards of _any_ user.
# admin_users: []

# Grafana configuration.
# Besides the admin_users defined statically in the config, LB is capable of
# synchronizing users from a given Grafana Team to add the users of this team
# to the admin users. The synchronization is done every 2 hours and thus, whenever
# a new user is added to Grafana Team, that user will have access to be able to
# access dashboards of all users by skipping additional checks
# grafana:
#
# # URL at which Grafana is running. If Grafana and CEEMS LB are running on the
# # same host, use the localhost. Else use the public URL of Grafana instance
# url: http://localhost:3000
#
# # If Grafana is using self signed TLS, set this option to true to skip TLS
# # certificate check
# skip_tls_verify: false
#
# # The ID of the Grafana team to fetch the users from.
# # IMPORTANT: The CEEMS LB service should have a GRAFANA_API_TOKEN environment
# # variable set to be able to fetch members of this Grafana team.
# # Operators can create a service account and create a API token with admin scope
# # in this service accoount and use that token for CEEMS LB service.
# admin_team_id: 1

# TLS is not supported for backends. CEEMS LB supports TLS and TLS terminates
# at the LB and requests are proxied to backends on HTTP.
#
Expand All @@ -24,5 +53,6 @@ strategy: resource-based
# be configured in URL with usual syntax.
backends:
- url: "http://localhost:9090"

# An example of configuring the basic auth username and password with backend
# - url: "http://alice:password@localhost:9091"
4 changes: 2 additions & 2 deletions cmd/ceems_lb/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ func TestCEEMSLBExecutable(t *testing.T) {
t.Error(err)
}

usagestats := exec.Command(
lb := exec.Command(
binary, "--path.data", tmpDir,
"--config.path", tmpConfigPath,
"--web.listen-address", address,
)
if err := runCommandAndTests(usagestats); err != nil {
if err := runCommandAndTests(lb); err != nil {
t.Error(err)
}
}
Expand Down
4 changes: 2 additions & 2 deletions etc/prometheus/rules/cpu-gpu-nodes.rules
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#
# At node level, power consumed by CPU and DRAM can be estimated as
#
# node_cpu_power = 0.9 * ipmi_power * (rapl_package/(rapl_package * rapl_dram))
# node_dram_power = 0.9 * ipmi_power * (rapl_dram/(rapl_package * rapl_dram))
# node_cpu_power = 0.9 * ipmi_power * (rapl_package/(rapl_package + rapl_dram))
# node_dram_power = 0.9 * ipmi_power * (rapl_dram/(rapl_package + rapl_dram))
#
# Now we have power usage at node level for CPU and DRAM. We split it further at the
# compute unit level using CPU time and DRAM usage by the compute unit. For network power usage, we split
Expand Down
4 changes: 2 additions & 2 deletions etc/prometheus/rules/cpu-only-nodes.rules
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#
# At node level, power consumed by CPU and DRAM can be estimated as
#
# node_cpu_power = 0.9 * ipmi_power * (rapl_package/(rapl_package * rapl_dram))
# node_dram_power = 0.9 * ipmi_power * (rapl_dram/(rapl_package * rapl_dram))
# node_cpu_power = 0.9 * ipmi_power * (rapl_package/(rapl_package + rapl_dram))
# node_dram_power = 0.9 * ipmi_power * (rapl_dram/(rapl_package + rapl_dram))
#
# Now we have power usage at node level for CPU and DRAM. We split it further at the
# compute unit level using CPU time and DRAM usage by the compute unit. For network power usage, we split
Expand Down
3 changes: 2 additions & 1 deletion pkg/api/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,11 @@ func (b *CEEMSServer) Main() error {
base.GrafanaAdminTeamID = *grafanaAdminTeamID
grafana, err := grafana.NewGrafana(*grafanaWebURL, *grafanaWebSkipTLSVerify, logger)
if err != nil {
return fmt.Errorf("failed to create Grafana: %s", err)
return fmt.Errorf("failed to create Grafana client: %s", err)
}
if grafana.Available() {
if err := grafana.Ping(); err != nil {
//lint:ignore ST1005 Grafana is a noun and need to capitalize!
return fmt.Errorf("Grafana at %s is unreachable: %s", grafana.URL.Redacted(), err)
}
}
Expand Down
18 changes: 17 additions & 1 deletion pkg/lb/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/alecthomas/kingpin/v2"
"github.com/go-kit/log/level"
internal_runtime "github.com/mahendrapaipuri/ceems/internal/runtime"
"github.com/mahendrapaipuri/ceems/pkg/grafana"
tsdb "github.com/mahendrapaipuri/ceems/pkg/lb/backend"
"github.com/mahendrapaipuri/ceems/pkg/lb/base"
"github.com/mahendrapaipuri/ceems/pkg/lb/frontend"
Expand Down Expand Up @@ -54,7 +55,7 @@ func (lb *CEEMSLoadBalancer) Main() error {
).Default("").String()
configFile = lb.App.Flag(
"config.file",
"Config file containing backend server web URLs.",
"Configuration file path.",
).Default("").String()
maxProcs = lb.App.Flag(
"runtime.gomaxprocs", "The target number of CPUs Go will run on (GOMAXPROCS)",
Expand Down Expand Up @@ -102,6 +103,18 @@ func (lb *CEEMSLoadBalancer) Main() error {
runtime.GOMAXPROCS(*maxProcs)
level.Debug(logger).Log("msg", "Go MAXPROCS", "procs", runtime.GOMAXPROCS(0))

// If Grafana config found, create a new Grafana client instance
var grafanaClient *grafana.Grafana
grafanaClient, err = grafana.NewGrafana(config.Grafana.URL, config.Grafana.SkipTLSVerify, logger)
if err != nil {
return fmt.Errorf("failed to create Grafana client: %s", err)
}
if grafanaClient.Available() {
if err := grafanaClient.Ping(); err != nil {
return fmt.Errorf("Grafana at %s is unreachable: %s", grafanaClient.URL.Redacted(), err)
}
}

// Create context that listens for the interrupt signal from the OS.
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
defer stop()
Expand All @@ -120,7 +133,10 @@ func (lb *CEEMSLoadBalancer) Main() error {
WebSystemdSocket: *systemdSocket,
WebConfigFile: *webConfigFile,
DBPath: config.DBPath,
AdminUsers: config.AdminUsers,
Manager: manager,
Grafana: grafanaClient,
GrafanaTeamID: config.Grafana.AdminTeamID,
}

// Create frontend instance
Expand Down
16 changes: 12 additions & 4 deletions pkg/lb/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ var mockCEEMSLBApp = *kingpin.New(
)

func queryLB(address string) error {
resp, err := http.Get(fmt.Sprintf("http://%s", address))
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s", address), nil)
if err != nil {
return err
}

req.Header.Add("X-Grafana-User", "usr1")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}

b, err := io.ReadAll(resp.Body)
if err != nil {
return err
Expand Down Expand Up @@ -94,9 +102,9 @@ func TestCEEMSLBMainSuccess(t *testing.T) {
func TestCEEMSLBMainFail(t *testing.T) {
// Remove test related args and add a dummy arg
os.Args = []string{os.Args[0]}
a := CEEMSLoadBalancer{
appName: mockCEEMSLBAppName,
App: mockCEEMSLBApp,
a, err := NewCEEMSLoadBalancer()
if err != nil {
t.Fatal(err)
}

// Start Main
Expand Down
15 changes: 12 additions & 3 deletions pkg/lb/cli/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@ import (
"gopkg.in/yaml.v2"
)

// Grafana defines Grafana server struct
type Grafana struct {
URL string `yaml:"url"`
SkipTLSVerify bool `yaml:"skip_tls_verify"`
AdminTeamID string `yaml:"admin_team_id"`
}

// Backend defines backend server
type Backend struct {
URL string `yaml:"url"`
}

// Config defines the backend servers config
type Config struct {
Backends []Backend `yaml:"backends"`
Strategy string `yaml:"strategy"`
DBPath string `yaml:"db_path"`
Backends []Backend `yaml:"backends"`
Strategy string `yaml:"strategy"`
DBPath string `yaml:"db_path"`
AdminUsers []string `yaml:"admin_users"`
Grafana Grafana `yaml:"grafana"`
}

func getLBConfig(filePath string) (*Config, error) {
Expand Down
Loading
Loading