Skip to content

Commit 819f428

Browse files
authored
[app] Implement Authentication (#406)
Instead of relying on a third party service like OAtuh2 Proxy for authenticating users, we are now supporting authentication of users directly within kobs. Users can be authenticated using a static list of email and password combinations or via OIDC.
1 parent ef0c280 commit 819f428

File tree

86 files changed

+1311
-1138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1311
-1138
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
2020
- [#399](https://github.com/kobsio/kobs/pull/399): [github] Add new `usernotifications` panel and allow users to use the plugin within the Notifications.
2121
- [#401](https://github.com/kobsio/kobs/pull/401): [app] Add integrations for Kubernetes Resource, which allows administrators to define a set of default dashboards, which are added to each resource.
2222
- [#402](https://github.com/kobsio/kobs/pull/402): [app] Add `mongodb` driver as alternative to the existing `bolt` driver.
23+
- [#406](https://github.com/kobsio/kobs/pull/406): [app] :warning: _Breaking change:_ :warning: Implement authentication, so that no third party service like [OAuth2-Proxy](https://oauth2-proxy.github.io/oauth2-proxy/) is required to grant users access to kobs.
2324
- [#407](https://github.com/kobsio/kobs/pull/407): [sql] Add `singlestats` chart to render single values returned by a query.
2425
- [#411](https://github.com/kobsio/kobs/pull/411): [sql] Add `yAxisGroup` property for charts.
2526

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ kobs brings your metrics, logs, traces and Kubernetes into one place, to provide
2121
- **Prometheus:** Access your Prometheus directly in kobs next to your Kubernetes resources.
2222
- **Elasticsearch and Jaeger:** View the logs from Elasticsearch and traces from Jaeger, where it matters.
2323
- **Istio:** Get the topology graph from Kiali for your Istio service mesh directly in kobs.
24-
- **Authentication and Authorization:** Manage the access to kobs via [OAuth2-Proxy](https://oauth2-proxy.github.io/oauth2-proxy/) and provide your developers the permissions they need via Teams and Users CRs.
24+
- **Authentication and Authorization:** Manage the access to kobs via OIDC and provide your developers the permissions they need via Teams and Users CRs.
2525

2626
## Contributing
2727

cmd/kobs/hub/config/config.go

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66

77
"github.com/kobsio/kobs/pkg/hub/api"
8+
"github.com/kobsio/kobs/pkg/hub/auth"
89
"github.com/kobsio/kobs/pkg/hub/satellites"
910

1011
"sigs.k8s.io/yaml"
@@ -13,6 +14,7 @@ import (
1314
// Config is the complete configuration for kobs.
1415
type Config struct {
1516
Satellites satellites.Config `json:"satellites"`
17+
Auth auth.Config `json:"auth"`
1618
API api.Config `json:"api"`
1719
}
1820

@@ -25,11 +27,21 @@ func Load(file string) (*Config, error) {
2527
return nil, err
2628
}
2729

30+
// For the hub we have to unmarshal the configuration file twice. The first time we do not replace the file content
31+
// with environment variables and the seconde time we replace the environment variables. This is required, because
32+
// the hashed user passwords will not be usabe after replacing.
33+
cfgNotReplaced := &Config{}
34+
if err := yaml.Unmarshal(configContent, cfgNotReplaced); err != nil {
35+
return nil, err
36+
}
37+
2838
configContent = []byte(os.ExpandEnv(string(configContent)))
2939
cfg := &Config{}
3040
if err := yaml.Unmarshal(configContent, cfg); err != nil {
3141
return nil, err
3242
}
3343

44+
cfg.Auth.Users = cfgNotReplaced.Auth.Users
45+
3446
return cfg, nil
3547
}

cmd/kobs/hub/hub.go

+7-41
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/kobsio/kobs/cmd/kobs/hub/config"
1111
"github.com/kobsio/kobs/pkg/app"
1212
"github.com/kobsio/kobs/pkg/hub"
13+
"github.com/kobsio/kobs/pkg/hub/auth"
1314
"github.com/kobsio/kobs/pkg/hub/satellites"
1415
"github.com/kobsio/kobs/pkg/hub/store"
1516
"github.com/kobsio/kobs/pkg/hub/watcher"
@@ -34,12 +35,6 @@ func Command() *cobra.Command {
3435
var hubWatcherInterval time.Duration
3536
var hubWatcherWorker int64
3637
var metricsAddress string
37-
var authEnabled bool
38-
var authHeaderUser string
39-
var authHeaderTeams string
40-
var authLogoutRedirect string
41-
var authSessionToken string
42-
var authSessionInterval time.Duration
4338

4439
defaultAppAddress := ":15219"
4540
if os.Getenv("KOBS_APP_ADDRESS") != "" {
@@ -97,34 +92,6 @@ func Command() *cobra.Command {
9792
defaultMetricsAddress = os.Getenv("KOBS_METRICS_ADDRESS")
9893
}
9994

100-
defaultAuthHeaderUser := "X-Auth-Request-Email"
101-
if os.Getenv("KOBS_AUTH_HEADER_USER") != "" {
102-
defaultAuthHeaderUser = os.Getenv("KOBS_AUTH_HEADER_USER")
103-
}
104-
105-
defaultAuthHeaderTeams := "X-Auth-Request-Groups"
106-
if os.Getenv("KOBS_AUTH_HEADER_TEAMS") != "" {
107-
defaultAuthHeaderTeams = os.Getenv("KOBS_AUTH_HEADER_TEAMS")
108-
}
109-
110-
defaultAuthLogoutRedirect := "/oauth2/sign_out"
111-
if os.Getenv("KOBS_AUTH_LOGOUT_REDIRECT") != "" {
112-
defaultAuthLogoutRedirect = os.Getenv("KOBS_AUTH_LOGOUT_REDIRECT")
113-
}
114-
115-
defaultAuthSessionToken := ""
116-
if os.Getenv("KOBS_AUTH_SESSION_TOKEN") != "" {
117-
defaultAuthSessionToken = os.Getenv("KOBS_AUTH_SESSION_TOKEN")
118-
}
119-
120-
defaultAuthSessionInterval := time.Duration(48 * time.Hour)
121-
if os.Getenv("KOBS_AUTH_SESSION_INTERVAL") != "" {
122-
parsedDefaultAuthSessionInterval, err := time.ParseDuration(os.Getenv("KOBS_AUTH_SESSION_INTERVAL"))
123-
if err == nil && parsedDefaultAuthSessionInterval > 60*time.Second {
124-
defaultAuthSessionInterval = parsedDefaultAuthSessionInterval
125-
}
126-
}
127-
12895
hubCmd := &cobra.Command{
12996
Use: "hub",
13097
Short: "Hub component of kobs.",
@@ -174,6 +141,11 @@ func Command() *cobra.Command {
174141
log.Fatal(nil, "Could not create store", zap.Error(err))
175142
}
176143

144+
authClient, err := auth.NewClient(cfg.Auth, storeClient)
145+
if err != nil {
146+
log.Fatal(nil, "Could not create auth client", zap.Error(err))
147+
}
148+
177149
var watcherClient watcher.Client
178150
if hubMode == "default" || hubMode == "watcher" {
179151
watcherClient, err = watcher.NewClient(hubWatcherInterval, hubWatcherWorker, satellitesClient, storeClient)
@@ -191,7 +163,7 @@ func Command() *cobra.Command {
191163
var appServer app.Server
192164

193165
if hubMode == "default" || hubMode == "server" {
194-
hubSever, err = hub.New(cfg.API, debugUsername, debugPassword, hubAddress, authEnabled, authHeaderUser, authHeaderTeams, authLogoutRedirect, authSessionToken, authSessionInterval, satellitesClient, storeClient)
166+
hubSever, err = hub.New(cfg.API, debugUsername, debugPassword, hubAddress, authClient, satellitesClient, storeClient)
195167
if err != nil {
196168
log.Fatal(nil, "Could not create hub server", zap.Error(err))
197169
}
@@ -249,12 +221,6 @@ func Command() *cobra.Command {
249221
hubCmd.PersistentFlags().DurationVar(&hubWatcherInterval, "hub.watcher.interval", defaultHubWatcherInterval, "The interval for the watcher to sync the satellite configuration.")
250222
hubCmd.PersistentFlags().Int64Var(&hubWatcherWorker, "hub.watcher.worker", defaultHubWatcherWorker, "The number of parallel sync processes for the watcher.")
251223
hubCmd.PersistentFlags().StringVar(&metricsAddress, "metrics.address", defaultMetricsAddress, "The address, where the metrics server is listen on.")
252-
hubCmd.PersistentFlags().BoolVar(&authEnabled, "auth.enabled", false, "Enable the authentication and authorization middleware.")
253-
hubCmd.PersistentFlags().StringVar(&authHeaderUser, "auth.header.user", defaultAuthHeaderUser, "The header, which contains the user id.")
254-
hubCmd.PersistentFlags().StringVar(&authHeaderTeams, "auth.header.teams", defaultAuthHeaderTeams, "The header, which contains the team ids.")
255-
hubCmd.PersistentFlags().StringVar(&authLogoutRedirect, "auth.logout.redirect", defaultAuthLogoutRedirect, "The redirect url which should be used, when the user clicks on the logout button.")
256-
hubCmd.PersistentFlags().StringVar(&authSessionToken, "auth.session.token", defaultAuthSessionToken, "The token to encrypt the session cookie.")
257-
hubCmd.PersistentFlags().DurationVar(&authSessionInterval, "auth.session.interval", defaultAuthSessionInterval, "The interval for how long a session is valid.")
258224

259225
return hubCmd
260226
}

deploy/helm/hub/Chart.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ description: Kubernetes Observability Platform
44
type: application
55
home: https://kobs.io
66
icon: https://kobs.io/assets/images/logo.svg
7-
version: 0.17.0
7+
version: 0.18.0
88
appVersion: v0.9.1

deploy/helm/hub/templates/deployment.yaml

-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ spec:
4343
- --hub.store.uri={{ .Values.hub.settings.store.uri }}
4444
- --hub.watcher.interval={{ .Values.hub.settings.watcher.interval }}
4545
- --hub.watcher.worker={{ .Values.hub.settings.watcher.worker }}
46-
- --auth.enabled={{ .Values.hub.settings.auth.enabled }}
47-
- --auth.header.user={{ .Values.hub.settings.auth.headerUser }}
48-
- --auth.header.teams={{ .Values.hub.settings.auth.headerTeams }}
49-
- --auth.logout.redirect={{ .Values.hub.settings.auth.logoutRedirect }}
50-
- --auth.session.interval={{ .Values.hub.settings.auth.sessiontInterval }}
5146
{{- with .Values.env }}
5247
env:
5348
{{- toYaml . | nindent 12 }}

deploy/helm/hub/values.yaml

+1-8
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,6 @@ hub:
132132
watcher:
133133
interval: 300s
134134
worker: 10
135-
auth:
136-
enabled: false
137-
headerUser: X-Auth-Request-Email
138-
headerTeams: X-Auth-Request-Groups
139-
logoutRedirect: /oauth2/sign_out
140-
sessiontInterval: 48h0m0s
141135

142136
## Set the content of the config.yaml file, which is used by kobs. The configuration file is used to specify the
143137
## cluster providers and the configuration for the plugins.
@@ -165,8 +159,7 @@ istio:
165159

166160
timeout: 300s
167161

168-
## You can also add your own routes to the VirtualService. This can be used to add an oauth2-proxy to handle the
169-
## authentication for the dashboard.
162+
## You can also add your own routes to the VirtualService.
170163
##
171164
additionalRoutes: []
172165

deploy/helm/satellite/Chart.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ description: Kubernetes Observability Platform
44
type: application
55
home: https://kobs.io
66
icon: https://kobs.io/assets/images/logo.svg
7-
version: 0.17.0
7+
version: 0.18.0
88
appVersion: v0.9.1

deploy/helm/satellite/values.yaml

+1-2
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ istio:
154154

155155
timeout: 300s
156156

157-
## You can also add your own routes to the VirtualService. This can be used to add an oauth2-proxy to handle the
158-
## authentication for the dashboard.
157+
## You can also add your own routes to the VirtualService.
159158
##
160159
additionalRoutes: []
161160

deploy/kustomize/hub/deployment.yaml

-5
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ spec:
3232
- --hub.store.uri=/tmp/kobs.db
3333
- --hub.watcher.interval=300s
3434
- --hub.watcher.worker=10
35-
- --auth.enabled=false
36-
- --auth.header.user=X-Auth-Request-Email
37-
- --auth.header.teams=X-Auth-Request-Groups
38-
- --auth.logout.redirect=/oauth2/sign_out
39-
- --auth.session.interval=48h0m0s
4035
ports:
4136
- name: http-web
4237
containerPort: 15219
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Authentication and Authorization
2+
3+
kobs supports the authentication and authorization of users. Users can be authenticated using a static list of configured email and password combinations or using OIDC. Authorization is handled via the permissions set in a [User CR](../../resources/users.md) or a [Team CR](../../resources/teams.md). An authenticated user is connected a corresponding User CR and Team CR via the email and groups claim from the OIDC flow.
4+
5+
```yaml
6+
auth:
7+
# Enable authentication and authorization of of users.
8+
enabled: true
9+
# OIDC configuration for kobs. OIDC can be used next to the static user list to authenticate and authorize users. The OIDC provider must be enabled explizit. If the configuration is wrong kobs will crash during the startup process.
10+
oidc:
11+
enabled: true
12+
# The issuer (e.g. "https://accounts.google.com"), client id and client secret for your OIDC provider.
13+
issuer:
14+
clientID:
15+
clientSecret:
16+
# The url where the OIDC provider redirects a user after login. Must be the URL where your kobs instance is running at.
17+
redirectURL:
18+
# A random string to mitigate CSRF attacks.
19+
state:
20+
# The scopes for the OIDC provider. By default we need the "openid", "profile", "email", "groups" scope. If your OIDC provider (e.g. Google) does not support the "groups" scope you can also omit it.
21+
# The "groups" scope is needed to connect a user with a team, so that you can set the permissions of users in a team and not for each single user.
22+
# If you are using Google and want to use Google Groups to connect your users with teams, you can use a tool like Dex (https://dexidp.io) to get the groups of a user.
23+
scopes: ["openid", "profile", "email", "groups"]
24+
# Session configuration for kobs.
25+
session:
26+
# The token must be a random string which is used to sign the JWT token, which is generated when a user is authenticated.
27+
token:
28+
# The interval defines the lifetime of the generated token. When the token is expired the user must authenticate again.
29+
interval: 48m
30+
# A static list of users which can be access kobs. Each user must have a email address and password.
31+
# ATTENTION: Substitution of environment variables is not supported for the user configuration. Instead you can directly use the hashed password within the configuration.
32+
users:
33+
- email:
34+
# The hashed password of the user. The password can be generated using htpasswd (https://httpd.apache.org/docs/2.4/programs/htpasswd.html).
35+
# htpasswd -nBC 10 "" | tr -d ':\n'
36+
# That command will prompt you for a password and output the hashed password, which will look something like:
37+
# $2y$10$dqqr3NIClzy4.jDQ3bHpveqVVxSqmpeP8oRI.eTZd91KxL8EyZx0e
38+
password:
39+
# An optional list of groups to authorize a user to access resources based on the permissions of the corresponding Team CRs.
40+
# groups: ["dia@kobs.io"]
41+
# See https://kobs.io/main/resources/teams/#example for an example Team CR.
42+
groups:
43+
```

0 commit comments

Comments
 (0)