add glauth fallback backend

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2020-10-05 17:12:40 +02:00
parent f10950d6e8
commit cbbfeec35b
15 changed files with 501 additions and 801 deletions

View File

@@ -0,0 +1,8 @@
Enhancement: Add glauth fallback backend
We introduced the `fallback-datastore` config option and the corresponding options to allow configuring a simple chain of two handlers.
Simple, because it is intended for bind and single result search queries. Merging large sets of results is currently out of scope. For now, the implementation will only search the fallback backend if the default backend returns an error or the number of results is 0. This is sufficient to allow an IdP to authenticate users from ocis as well as owncloud 10 as described in the [bridge scenario](https://owncloud.github.io/ocis/bridge/).
https://github.com/owncloud/ocis/pull/649
https://github.com/owncloud/ocis-glauth/issues/18

View File

@@ -7,8 +7,6 @@ geekdocEditPath: edit/master/docs/extensions/glauth
geekdocFilePath: _index.md
---
This service provides a simple glauth world API which can be used by clients or other extensions.
This service provides a [glauth](https://github.com/glauth/glauth) based LDAP proxy for ocis which can be used by clients or other extensions. It allows applications relying on LDAP to access the accounts stored in the ocis accounts service. It can be used to make firewalls or identity providers aware of all users, including guest accounts.
- reiner proxy
ldap für eos und firewall
- backend ist der accounts service
We are using it to make eos aware of all accounts so the native ACLs can be used to persist share information in the storage.

View File

@@ -9,264 +9,6 @@ geekdocFilePath: getting-started.md
{{< toc >}}
## Installation
## Configuration Tips
So far we are offering two different variants for the installation. You can choose between [Docker](https://www.docker.com/) or pre-built binaries which are stored on our download mirrors and GitHub releases. Maybe we will also provide system packages for the major distributions later if we see the need for it.
### Docker
TBD
### Binaries
TBD
## Configuration
We provide overall three different variants of configuration. The variant based on environment variables and commandline flags are split up into global values and command-specific values.
### Envrionment variables
If you prefer to configure the service with environment variables you can see the available variables below.
#### Global
GLAUTH_CONFIG_FILE
: Path to config file, empty default value
GLAUTH_LOG_LEVEL
: Set logging level, defaults to `info`
GLAUTH_LOG_COLOR
: Enable colored logging, defaults to `true`
GLAUTH_LOG_PRETTY
: Enable pretty logging, defaults to `true`
#### Server
GLAUTH_TRACING_ENABLED
: Enable sending traces, defaults to `false`
GLAUTH_TRACING_TYPE
: Tracing backend type, defaults to `jaeger`
GLAUTH_TRACING_ENDPOINT
: Endpoint for the agent, empty default value
GLAUTH_TRACING_COLLECTOR
: Endpoint for the collector, empty default value
GLAUTH_TRACING_SERVICE
: Service name for tracing, defaults to `glauth`
GLAUTH_DEBUG_ADDR
: Address to bind debug server, defaults to `0.0.0.0:9124`
GLAUTH_DEBUG_TOKEN
: Token to grant metrics access, empty default value
GLAUTH_DEBUG_PPROF
: Enable pprof debugging, defaults to `false`
GLAUTH_DEBUG_ZPAGES
: Enable zpages debugging, defaults to `false`
GLAUTH_HTTP_ADDR
: Address to bind http server, defaults to `0.0.0.0:9120`
GLAUTH_HTTP_NAMESPACE
: The http namespace
GLAUTH_HTTP_ROOT
: Root path of http server, defaults to `/`
#### Health
GLAUTH_DEBUG_ADDR
: Address to debug endpoint, defaults to `0.0.0.0:9124`
### Commandline flags
If you prefer to configure the service with commandline flags you can see the available variables below.
#### Global
--config-file
: Path to config file, empty default value
--log-level
: Set logging level, defaults to `info`
--log-color
: Enable colored logging, defaults to `true`
--log-pretty
: Enable pretty logging, defaults to `true`
#### Server
--tracing-enabled
: Enable sending traces, defaults to `false`
--tracing-type
: Tracing backend type, defaults to `jaeger`
--tracing-endpoint
: Endpoint for the agent, empty default value
--tracing-collector
: Endpoint for the collector, empty default value
--tracing-service
: Service name for tracing, defaults to `glauth`
--debug-addr
: Address to bind debug server, defaults to `0.0.0.0:9124`
--debug-token
: Token to grant metrics access, empty default value
--debug-pprof
: Enable pprof debugging, defaults to `false`
--debug-zpages
: Enable zpages debugging, defaults to `false`
--http-addr
: Address to bind http server, defaults to `0.0.0.0:9120`
--http-namespace
: Namespace for internal services communication, defaults to `com.owncloud.web`
--http-root
: Root path of http server, defaults to `/`
#### Health
--debug-addr
: Address to debug endpoint, defaults to `0.0.0.0:9124`
### Configuration file
So far we support the file formats `JSON` and `YAML`, if you want to get a full example configuration just take a look at [our repository](https://github.com/owncloud/ocis/glauth/tree/master/config), there you can always see the latest configuration format. These example configurations include all available options and the default values. The configuration file will be automatically loaded if it's placed at `/etc/ocis/glauth.yml`, `${HOME}/.ocis/glauth.yml` or `$(pwd)/config/glauth.yml`.
## Usage
The program provides a few sub-commands on execution. The available configuration methods have already been mentioned above. Generally you can always see a formated help output if you execute the binary via `ocis-glauth --help`.
### Server
The server command is used to start the http and debug server on two addresses within a single process. The http server is serving the general webservice while the debug server is used for health check, readiness check and to server the metrics mentioned below. For further help please execute:
{{< highlight txt >}}
ocis-glauth server --help
{{< / highlight >}}
### Health
The health command is used to execute a health check, if the exit code equals zero the service should be up and running, if the exist code is greater than zero the service is not in a healthy state. Generally this command is used within our Docker containers, it could also be used within Kubernetes.
{{< highlight txt >}}
ocis-glauth health --help
{{< / highlight >}}
## Metrics
This service provides some [Prometheus](https://prometheus.io/) metrics through the debug endpoint, you can optionally secure the metrics endpoint by some random token, which got to be configured through one of the flag `--debug-token` or the environment variable `GLAUTH_DEBUG_TOKEN` mentioned above. By default the metrics endpoint is bound to `http://0.0.0.0:9124/metrics`.
go_gc_duration_seconds
: A summary of the GC invocation durations
go_gc_duration_seconds_sum
: A summary of the GC invocation durations
go_gc_duration_seconds_count
: A summary of the GC invocation durations
go_goroutines
: Number of goroutines that currently exist
go_info
: Information about the Go environment
go_memstats_alloc_bytes
: Number of bytes allocated and still in use
go_memstats_alloc_bytes_total
: Total number of bytes allocated, even if freed
go_memstats_buck_hash_sys_bytes
: Number of bytes used by the profiling bucket hash table
go_memstats_frees_total
: Total number of frees
go_memstats_gc_cpu_fraction
: The fraction of this program's available CPU time used by the GC since the program started
go_memstats_gc_sys_bytes
: Number of bytes used for garbage collection system metadata
go_memstats_heap_alloc_bytes
: Number of heap bytes allocated and still in use
go_memstats_heap_idle_bytes
: Number of heap bytes waiting to be used
go_memstats_heap_inuse_bytes
: Number of heap bytes that are in use
go_memstats_heap_objects
: Number of allocated objects
go_memstats_heap_released_bytes
: Number of heap bytes released to OS
go_memstats_heap_sys_bytes
: Number of heap bytes obtained from system
go_memstats_last_gc_time_seconds
: Number of seconds since 1970 of last garbage collection
go_memstats_lookups_total
: Total number of pointer lookups
go_memstats_mallocs_total
: Total number of mallocs
go_memstats_mcache_inuse_bytes
: Number of bytes in use by mcache structures
go_memstats_mcache_sys_bytes
: Number of bytes used for mcache structures obtained from system
go_memstats_mspan_inuse_bytes
: Number of bytes in use by mspan structures
go_memstats_mspan_sys_bytes
: Number of bytes used for mspan structures obtained from system
go_memstats_next_gc_bytes
: Number of heap bytes when next garbage collection will take place
go_memstats_other_sys_bytes
: Number of bytes used for other system allocations
go_memstats_stack_inuse_bytes
: Number of bytes in use by the stack allocator
go_memstats_stack_sys_bytes
: Number of bytes obtained from system for stack allocator
go_memstats_sys_bytes
: Number of bytes obtained from system
go_threads
: Number of OS threads created
promhttp_metric_handler_requests_in_flight
: Current number of scrapes being served
promhttp_metric_handler_requests_total
: Total number of scrapes by HTTP status code
The default setup does not use a fallback backend. It can be enabled by setting the `GLAUTH_FALLBACK_DATASTORE` environment variable. When using `owncloud` make sure to use the full URL to the [ownCloud 10 graph api app](https://github.com/owncloud/graphapi) endpoint, eg.: `GLAUTH_FALLBACK_SERVERS="https://demo.owncloud.com/apps/graphapi/v1.0"`

View File

@@ -5,22 +5,23 @@ go 1.13
require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1
contrib.go.opencensus.io/exporter/ocagent v0.7.0
contrib.go.opencensus.io/exporter/zipkin v0.1.1
contrib.go.opencensus.io/exporter/zipkin v0.1.2
github.com/GeertJohan/yubigo v0.0.0-20190917122436-175bc097e60e
github.com/UnnoTed/fileb0x v1.1.4
github.com/glauth/glauth v1.1.3-0.20200228160118-2d4f5d547682
github.com/glauth/glauth v1.1.3-0.20201005201919-4d42af8aacbf
github.com/go-logr/logr v0.1.0
github.com/micro/cli/v2 v2.1.2
github.com/micro/go-micro/v2 v2.9.1
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/nmcclain/ldap v0.0.0-20191021200707-3b3b69a7e9e3
github.com/oklog/run v1.1.0
github.com/openzipkin/zipkin-go v0.2.2
github.com/owncloud/ocis/accounts v0.0.0-20200918125107-fcca9faa81c8
github.com/openzipkin/zipkin-go v0.2.5
github.com/owncloud/ocis/accounts v0.5.2
github.com/owncloud/ocis/ocis-pkg v0.0.0-20200918114005-1a0ddd2190ee
github.com/prometheus/client_golang v1.7.1
github.com/restic/calens v0.2.0
github.com/rs/zerolog v1.19.0
github.com/spf13/viper v1.7.0
github.com/rs/zerolog v1.20.0
github.com/spf13/viper v1.7.1
go.opencensus.io v0.22.4
)

View File

@@ -32,6 +32,8 @@ contrib.go.opencensus.io/exporter/ocagent v0.7.0/go.mod h1:IshRmMJBhDfFj5Y67nVhM
contrib.go.opencensus.io/exporter/prometheus v0.2.0/go.mod h1:TYmVAyE8Tn1lyPcltF5IYYfWp2KHu7lQGIZnj8iZMys=
contrib.go.opencensus.io/exporter/zipkin v0.1.1 h1:PR+1zWqY8ceXs1qDQQIlgXe+sdiwCf0n32bH4+Epk8g=
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
contrib.go.opencensus.io/exporter/zipkin v0.1.2 h1:YqE293IZrKtqPnpwDPH/lOqTWD/s3Iwabycam74JV3g=
contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -277,8 +279,8 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/glauth/glauth v1.1.3-0.20200228160118-2d4f5d547682 h1:8qan0vNLF7i9Wq07mhTn/60hXEPdGTYJnR82P4X818s=
github.com/glauth/glauth v1.1.3-0.20200228160118-2d4f5d547682/go.mod h1:ygO1z1pcp79iBrjbA6vqrsUxIonStjBncosl2a9/Dx8=
github.com/glauth/glauth v1.1.3-0.20201005201919-4d42af8aacbf h1:3ejnL7OvxCJ6XiEJjv16odGGUPvZlqjfDLefPVF7Vrw=
github.com/glauth/glauth v1.1.3-0.20201005201919-4d42af8aacbf/go.mod h1:ygO1z1pcp79iBrjbA6vqrsUxIonStjBncosl2a9/Dx8=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
@@ -882,6 +884,8 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU=
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/ory/fosite v0.29.0/go.mod h1:0atSZmXO7CAcs6NPMI/Qtot8tmZYj04Nddoold4S2h0=
@@ -986,6 +990,8 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg=
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/rubenv/sql-migrate v0.0.0-20190212093014-1007f53448d7/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -1059,6 +1065,8 @@ github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/steveyen/gtreap v0.1.0 h1:CjhzTa274PyJLJuMZwIzCO1PfC00oRa8d1Kc78bFXJM=
github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=

View File

@@ -2,12 +2,13 @@ package command
import (
"context"
"github.com/owncloud/ocis/glauth/pkg/metrics"
"os"
"os/signal"
"strings"
"time"
"github.com/owncloud/ocis/glauth/pkg/metrics"
"github.com/owncloud/ocis/glauth/pkg/crypto"
"contrib.go.opencensus.io/exporter/jaeger"
@@ -42,6 +43,7 @@ func Server(cfg *config.Config) *cli.Command {
}
cfg.Backend.Servers = c.StringSlice("backend-server")
cfg.Fallback.Servers = c.StringSlice("fallback-server")
return ParseConfig(c, cfg)
},
@@ -143,17 +145,20 @@ func Server(cfg *config.Config) *cli.Command {
metrics.BuildInfo.WithLabelValues(cfg.Version).Set(1)
{
cfg := glauthcfg.Config{
LDAP: glauthcfg.LDAP{
Enabled: cfg.Ldap.Enabled,
Listen: cfg.Ldap.Address,
},
LDAPS: glauthcfg.LDAPS{
Enabled: cfg.Ldaps.Enabled,
Listen: cfg.Ldaps.Address,
Cert: cfg.Ldaps.Cert,
Key: cfg.Ldaps.Key,
},
lcfg := glauthcfg.LDAP{
Enabled: cfg.Ldap.Enabled,
Listen: cfg.Ldap.Address,
}
lscfg := glauthcfg.LDAPS{
Enabled: cfg.Ldaps.Enabled,
Listen: cfg.Ldaps.Address,
Cert: cfg.Ldaps.Cert,
Key: cfg.Ldaps.Key,
}
bcfg := glauthcfg.Config{
LDAP: lcfg, // TODO remove LDAP from the backend config upstream
LDAPS: lscfg, // TODO remove LDAP from the backend config upstream
Backend: glauthcfg.Backend{
Datastore: cfg.Backend.Datastore,
BaseDN: cfg.Backend.BaseDN,
@@ -165,8 +170,22 @@ func Server(cfg *config.Config) *cli.Command {
UseGraphAPI: cfg.Backend.UseGraphAPI,
},
}
fcfg := glauthcfg.Config{
LDAP: lcfg, // TODO remove LDAP from the backend config upstream
LDAPS: lscfg, // TODO remove LDAP from the backend config upstream
Backend: glauthcfg.Backend{
Datastore: cfg.Fallback.Datastore,
BaseDN: cfg.Fallback.BaseDN,
Insecure: cfg.Fallback.Insecure,
NameFormat: cfg.Fallback.NameFormat,
GroupFormat: cfg.Fallback.GroupFormat,
Servers: cfg.Fallback.Servers,
SSHKeyAttr: cfg.Fallback.SSHKeyAttr,
UseGraphAPI: cfg.Fallback.UseGraphAPI,
},
}
if cfg.LDAPS.Enabled {
if lscfg.Enabled {
// GenCert has side effects as it writes 2 files to the binary running location
if err := crypto.GenCert("ldap.crt", "ldap.key", logger); err != nil {
logger.Fatal().Err(err).Msgf("Could not generate test-certificate")
@@ -182,7 +201,10 @@ func Server(cfg *config.Config) *cli.Command {
glauth.AccountsService(as),
glauth.GroupsService(gs),
glauth.Logger(logger),
glauth.Config(&cfg),
glauth.LDAP(&lcfg),
glauth.LDAPS(&lscfg),
glauth.Backend(&bcfg),
glauth.Fallback(&fcfg),
)
if err != nil {

View File

@@ -58,15 +58,16 @@ type Backend struct {
// Config combines all available configuration parts.
type Config struct {
File string
Log Log
Debug Debug
HTTP HTTP
Tracing Tracing
Ldap Ldap
Ldaps Ldaps
Backend Backend
Version string
File string
Log Log
Debug Debug
HTTP HTTP
Tracing Tracing
Ldap Ldap
Ldaps Ldaps
Backend Backend
Fallback Backend
Version string
}
// New initializes a new configuration with or without defaults.

View File

@@ -159,14 +159,9 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"GLAUTH_LDAPS_KEY"},
Destination: &cfg.Ldaps.Key,
},
&cli.StringFlag{
Name: "backend-datastore",
Value: "accounts",
// TODO bring back config / flat file support
Usage: "datastore to use as the backend. one of accounts, ldap or owncloud",
EnvVars: []string{"GLAUTH_BACKEND_DATASTORE"},
Destination: &cfg.Backend.Datastore,
},
// backend config
&cli.StringFlag{
Name: "backend-basedn",
Value: "dc=example,dc=org",
@@ -174,13 +169,6 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"GLAUTH_BACKEND_BASEDN"},
Destination: &cfg.Backend.BaseDN,
},
&cli.BoolFlag{
Name: "backend-insecure",
Value: false,
Usage: "Allow insecure requests to the datastore",
EnvVars: []string{"GLAUTH_BACKEND_INSECURE"},
Destination: &cfg.Backend.Insecure,
},
&cli.StringFlag{
Name: "backend-name-format",
Value: "cn",
@@ -195,12 +183,6 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"GLAUTH_BACKEND_GROUP_FORMAT"},
Destination: &cfg.Backend.GroupFormat,
},
&cli.StringSliceFlag{
Name: "backend-server",
Value: cli.NewStringSlice("https://demo.owncloud.com"),
Usage: `--backend-server http://internal1.example.com [--backend-server http://internal2.example.com]`,
EnvVars: []string{"GLAUTH_BACKEND_SERVERS"},
},
&cli.StringFlag{
Name: "backend-ssh-key-attr",
Value: "sshPublicKey",
@@ -208,6 +190,27 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"GLAUTH_BACKEND_SSH_KEY_ATTR"},
Destination: &cfg.Backend.SSHKeyAttr,
},
&cli.StringFlag{
Name: "backend-datastore",
Value: "accounts",
// TODO bring back config / flat file support
Usage: "datastore to use as the backend. one of accounts, ldap or owncloud",
EnvVars: []string{"GLAUTH_BACKEND_DATASTORE"},
Destination: &cfg.Backend.Datastore,
},
&cli.BoolFlag{
Name: "backend-insecure",
Value: false,
Usage: "Allow insecure requests to the datastore",
EnvVars: []string{"GLAUTH_BACKEND_INSECURE"},
Destination: &cfg.Backend.Insecure,
},
&cli.StringSliceFlag{
Name: "backend-server",
Value: cli.NewStringSlice("https://demo.owncloud.com/apps/graphapi/v1.0"),
Usage: `--backend-server http://internal1.example.com [--backend-server http://internal2.example.com]`,
EnvVars: []string{"GLAUTH_BACKEND_SERVERS"},
},
&cli.BoolFlag{
Name: "backend-use-graphapi",
Value: true,
@@ -215,5 +218,64 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"GLAUTH_BACKEND_USE_GRAPHAPI"},
Destination: &cfg.Backend.UseGraphAPI,
},
// fallback config
&cli.StringFlag{
Name: "fallback-basedn",
Value: "dc=example,dc=org",
Usage: "base distinguished name to expose",
EnvVars: []string{"GLAUTH_FALLBACK_BASEDN"},
Destination: &cfg.Fallback.BaseDN,
},
&cli.StringFlag{
Name: "fallback-name-format",
Value: "cn",
Usage: "name attribute for entries to expose. typically cn or uid",
EnvVars: []string{"GLAUTH_FALLBACK_NAME_FORMAT"},
Destination: &cfg.Fallback.NameFormat,
},
&cli.StringFlag{
Name: "fallback-group-format",
Value: "ou",
Usage: "name attribute for entries to expose. typically ou, cn or dc",
EnvVars: []string{"GLAUTH_FALLBACK_GROUP_FORMAT"},
Destination: &cfg.Fallback.GroupFormat,
},
&cli.StringFlag{
Name: "fallback-ssh-key-attr",
Value: "sshPublicKey",
Usage: "ssh key attribute for entries to expose",
EnvVars: []string{"GLAUTH_FALLBACK_SSH_KEY_ATTR"},
Destination: &cfg.Fallback.SSHKeyAttr,
},
&cli.StringFlag{
Name: "fallback-datastore",
Value: "",
// TODO bring back config / flat file support
Usage: "datastore to use as the fallback. one of accounts, ldap or owncloud",
EnvVars: []string{"GLAUTH_FALLBACK_DATASTORE"},
Destination: &cfg.Fallback.Datastore,
},
&cli.BoolFlag{
Name: "fallback-insecure",
Value: false,
Usage: "Allow insecure requests to the datastore",
EnvVars: []string{"GLAUTH_FALLBACK_INSECURE"},
Destination: &cfg.Fallback.Insecure,
},
&cli.StringSliceFlag{
Name: "fallback-server",
Value: cli.NewStringSlice("https://demo.owncloud.com/apps/graphapi/v1.0"),
Usage: `--fallback-server http://internal1.example.com [--fallback-server http://internal2.example.com]`,
EnvVars: []string{"GLAUTH_FALLBACK_SERVERS"},
},
&cli.BoolFlag{
Name: "fallback-use-graphapi",
Value: true,
Usage: "use Graph API, only for owncloud datastore",
EnvVars: []string{"GLAUTH_FALLBACK_USE_GRAPHAPI"},
Destination: &cfg.Fallback.UseGraphAPI,
},
}
}

View File

@@ -0,0 +1,110 @@
package glauth
import (
"net"
"github.com/glauth/glauth/pkg/handler"
"github.com/nmcclain/ldap"
"github.com/owncloud/ocis/ocis-pkg/log"
)
type chainHandler struct {
log log.Logger
b handler.Handler
f handler.Handler
}
func (h chainHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (res ldap.LDAPResultCode, err error) {
h.log.Debug().
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Bind request")
res, err = h.b.Bind(bindDN, bindSimplePw, conn)
switch {
case err != nil:
h.log.Error().
Err(err).
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Bind request")
return h.f.Bind(bindDN, bindSimplePw, conn)
case res == ldap.LDAPResultInvalidCredentials:
return h.f.Bind(bindDN, bindSimplePw, conn)
}
return
}
func (h chainHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (res ldap.ServerSearchResult, err error) {
h.log.Debug().
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Search request")
res, err = h.b.Search(bindDN, searchReq, conn)
switch {
case err != nil:
h.log.Error().
Err(err).
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Search request")
return h.f.Search(bindDN, searchReq, conn)
case len(res.Entries) == 0:
// yes, we only fall back if there are no results in the first backend
// this is not supposed to work for searching lots of users, only to look up a single user
// searching multiple users would require merging result sets. out of scope for now.
return h.f.Search(bindDN, searchReq, conn)
}
return
}
func (h chainHandler) Close(boundDN string, conn net.Conn) error {
h.log.Debug().
Str("boundDN", boundDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Close request")
if err := h.b.Close(boundDN, conn); err != nil {
h.log.Error().
Err(err).
Str("boundDN", boundDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Close request")
}
if err := h.f.Close(boundDN, conn); err != nil {
h.log.Error().
Err(err).
Str("boundDN", boundDN).
Interface("src", conn.RemoteAddr()).
Str("handler", "chain").
Msg("Close request")
}
return nil
}
// Add is not yet supported for the chain backend
func (h chainHandler) Add(boundDN string, req ldap.AddRequest, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// Modify is not yet supported for the chain backend
func (h chainHandler) Modify(boundDN string, req ldap.ModifyRequest, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// Delete is not yet supported for the chain backend
func (h chainHandler) Delete(boundDN string, deleteDN string, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// NewChainHandler implements a chain backend with two backends
func NewChainHandler(log log.Logger, bh handler.Handler, fh handler.Handler) handler.Handler {
return chainHandler{
log: log,
b: bh,
f: fh,
}
}

View File

@@ -2,13 +2,11 @@ package glauth
import (
"context"
"errors"
"fmt"
"net"
"strconv"
"strings"
"github.com/glauth/glauth/pkg/config"
"github.com/glauth/glauth/pkg/handler"
"github.com/glauth/glauth/pkg/stats"
ber "github.com/nmcclain/asn1-ber"
@@ -25,19 +23,22 @@ const (
)
type ocisHandler struct {
as accounts.AccountsService
gs accounts.GroupsService
log log.Logger
cfg *config.Config
as accounts.AccountsService
gs accounts.GroupsService
log log.Logger
basedn string
nameFormat string
groupFormat string
}
func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAPResultCode, error) {
bindDN = strings.ToLower(bindDN)
baseDN := strings.ToLower("," + h.cfg.Backend.BaseDN)
baseDN := strings.ToLower("," + h.basedn)
h.log.Debug().
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Interface("src", conn.RemoteAddr()).
Msg("Bind request")
@@ -46,8 +47,9 @@ func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAP
// parse the bindDN - ensure that the bindDN ends with the BaseDN
if !strings.HasSuffix(bindDN, baseDN) {
h.log.Error().
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Interface("src", conn.RemoteAddr()).
Msg("BindDN not part of our BaseDN")
return ldap.LDAPResultInvalidCredentials, nil
@@ -55,6 +57,7 @@ func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAP
parts := strings.Split(strings.TrimSuffix(bindDN, baseDN), ",")
if len(parts) > 2 {
h.log.Error().
Str("handler", "ocis").
Str("binddn", bindDN).
Int("numparts", len(parts)).
Interface("src", conn.RemoteAddr()).
@@ -73,6 +76,7 @@ func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAP
})
if err != nil || len(res.Accounts) == 0 {
h.log.Error().
Str("handler", "ocis").
Str("username", userName).
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
@@ -82,6 +86,7 @@ func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAP
stats.Frontend.Add("bind_successes", 1)
h.log.Debug().
Str("handler", "ocis").
Str("binddn", bindDN).
Interface("src", conn.RemoteAddr()).
Msg("Bind success")
@@ -90,11 +95,12 @@ func (h ocisHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (ldap.LDAP
func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
bindDN = strings.ToLower(bindDN)
baseDN := strings.ToLower("," + h.cfg.Backend.BaseDN)
baseDN := strings.ToLower("," + h.basedn)
searchBaseDN := strings.ToLower(searchReq.BaseDN)
h.log.Debug().
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Interface("src", conn.RemoteAddr()).
Msg("Search request")
@@ -109,12 +115,12 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
if !strings.HasSuffix(bindDN, baseDN) {
return ldap.ServerSearchResult{
ResultCode: ldap.LDAPResultInsufficientAccessRights,
}, fmt.Errorf("search error: BindDN %s not in our BaseDN %s", bindDN, h.cfg.Backend.BaseDN)
}, fmt.Errorf("search error: BindDN %s not in our BaseDN %s", bindDN, h.basedn)
}
if !strings.HasSuffix(searchBaseDN, h.cfg.Backend.BaseDN) {
if !strings.HasSuffix(searchBaseDN, h.basedn) {
return ldap.ServerSearchResult{
ResultCode: ldap.LDAPResultInsufficientAccessRights,
}, fmt.Errorf("search error: search BaseDN %s is not in our BaseDN %s", searchBaseDN, h.cfg.Backend.BaseDN)
}, fmt.Errorf("search error: search BaseDN %s is not in our BaseDN %s", searchBaseDN, h.basedn)
}
var qtype queryType = ""
@@ -127,21 +133,23 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
var cf *ber.Packet
cf, err = ldap.CompileFilter(searchReq.Filter)
if err != nil {
h.log.Debug().
h.log.Error().
Err(err).
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Interface("src", conn.RemoteAddr()).
Msg("could not compile filter")
return ldap.ServerSearchResult{
ResultCode: ldap.LDAPResultOperationsError,
}, fmt.Errorf("Search Error: error parsing filter: %s", searchReq.Filter)
}, fmt.Errorf("Search Error: error compiling filter: %s, error: %s", searchReq.Filter, err.Error())
}
qtype, query, code, err = parseFilter(cf)
if err != nil {
return ldap.ServerSearchResult{
ResultCode: code,
}, fmt.Errorf("Search Error: error parsing filter: %s", searchReq.Filter)
}, fmt.Errorf("Search Error: error parsing filter: %s, error: %s", searchReq.Filter, err.Error())
}
// check if the searchBaseDN already has a username and add it to the query
@@ -156,8 +164,9 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
entries := []*ldap.Entry{}
h.log.Debug().
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Str("qtype", string(qtype)).
Str("query", query).
@@ -170,8 +179,9 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
if err != nil {
h.log.Error().
Err(err).
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Str("query", query).
Interface("src", conn.RemoteAddr()).
@@ -179,7 +189,7 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
return ldap.ServerSearchResult{
ResultCode: ldap.LDAPResultOperationsError,
}, errors.New("search error: error listing users")
}, fmt.Errorf("search error: error listing users")
}
entries = append(entries, h.mapAccounts(accounts.Accounts)...)
case groupsQuery:
@@ -189,8 +199,9 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
if err != nil {
h.log.Error().
Err(err).
Str("handler", "ocis").
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Str("query", query).
Interface("src", conn.RemoteAddr()).
@@ -198,15 +209,17 @@ func (h ocisHandler) Search(bindDN string, searchReq ldap.SearchRequest, conn ne
return ldap.ServerSearchResult{
ResultCode: ldap.LDAPResultOperationsError,
}, errors.New("search error: error listing groups")
}, fmt.Errorf("search error: error listing groups")
}
entries = append(entries, h.mapGroups(groups.Groups)...)
}
stats.Frontend.Add("search_successes", 1)
h.log.Debug().
Str("handler", "ocis").
Int("num_entries", len(entries)).
Str("binddn", bindDN).
Str("basedn", h.cfg.Backend.BaseDN).
Str("basedn", h.basedn).
Str("filter", searchReq.Filter).
Interface("src", conn.RemoteAddr()).
Msg("AP: Search OK")
@@ -254,11 +267,11 @@ func (h ocisHandler) mapAccounts(accounts []*accounts.Account) []*ldap.Entry {
}
dn := fmt.Sprintf("%s=%s,%s=%s,%s",
h.cfg.Backend.NameFormat,
h.nameFormat,
accounts[i].PreferredName,
h.cfg.Backend.GroupFormat,
h.groupFormat,
"users",
h.cfg.Backend.BaseDN,
h.basedn,
)
entries = append(entries, &ldap.Entry{DN: dn, Attributes: attrs})
}
@@ -284,11 +297,11 @@ func (h ocisHandler) mapGroups(groups []*accounts.Group) []*ldap.Entry {
}
dn := fmt.Sprintf("%s=%s,%s=%s,%s",
h.cfg.Backend.NameFormat,
h.nameFormat,
groups[i].OnPremisesSamAccountName,
h.cfg.Backend.GroupFormat,
h.groupFormat,
"groups",
h.cfg.Backend.BaseDN,
h.basedn,
)
memberUids := make([]string, len(groups[i].Members))
@@ -318,9 +331,20 @@ func parseFilter(f *ber.Packet) (queryType, string, ldap.LDAPResultCode, error)
var code ldap.LDAPResultCode
var err error
switch ldap.FilterMap[f.Tag] {
case "Present":
if len(f.Children) != 0 {
return "", "", ldap.LDAPResultOperationsError, fmt.Errorf("equality match must have no children, got %+v", f)
}
attribute := strings.ToLower(f.Data.String())
if attribute == "objectclass" {
// TODO implement proper present odata query, for now fall back to listing users
return "users", q, code, err
}
return qtype, q, ldap.LDAPResultUnwillingToPerform, fmt.Errorf("%s filter match for %s not implemented", ldap.FilterMap[f.Tag], attribute)
case "Equality Match":
if len(f.Children) != 2 {
return "", "", ldap.LDAPResultOperationsError, errors.New("equality match must have exactly two children")
return "", "", ldap.LDAPResultOperationsError, fmt.Errorf("equality match must have exactly two children")
}
attribute := strings.ToLower(f.Children[0].Value.(string))
value := f.Children[1].Value.(string)
@@ -333,6 +357,9 @@ func parseFilter(f *ber.Packet) (queryType, string, ldap.LDAPResultCode, error)
qtype = usersQuery
case "posixgroup", "groups":
qtype = groupsQuery
case "*":
// TODO not implemented yet
qtype = usersQuery
default:
qtype = ""
}
@@ -367,7 +394,7 @@ func parseFilter(f *ber.Packet) (queryType, string, ldap.LDAPResultCode, error)
return qtype, q, code, err
case "Substrings":
if len(f.Children) != 2 {
return "", "", ldap.LDAPResultOperationsError, errors.New("substrings filter must have exactly two children")
return "", "", ldap.LDAPResultOperationsError, fmt.Errorf("substrings filter must have exactly two children")
}
attribute := strings.ToLower(f.Children[0].Value.(string))
if len(f.Children[1].Children) != 1 {
@@ -424,7 +451,7 @@ func parseFilter(f *ber.Packet) (queryType, string, ldap.LDAPResultCode, error)
return qtype, strings.Join(subQueries, " "+strings.ToLower(ldap.FilterMap[f.Tag])+" "), ldap.LDAPResultSuccess, nil
case "Not":
if len(f.Children) != 1 {
return "", "", ldap.LDAPResultOperationsError, errors.New("not filter match must have exactly one child")
return "", "", ldap.LDAPResultOperationsError, fmt.Errorf("not filter match must have exactly one child")
}
qtype, subQuery, code, err := parseFilter(f.Children[0])
if err != nil {
@@ -448,15 +475,32 @@ func (h ocisHandler) Close(boundDN string, conn net.Conn) error {
return nil
}
// Add is not yet supported for the ocis backend
func (h ocisHandler) Add(boundDN string, req ldap.AddRequest, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// Modify is not yet supported for the ocis backend
func (h ocisHandler) Modify(boundDN string, req ldap.ModifyRequest, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// Delete is not yet supported for the ocis backend
func (h ocisHandler) Delete(boundDN string, deleteDN string, conn net.Conn) (result ldap.LDAPResultCode, err error) {
return ldap.LDAPResultInsufficientAccessRights, nil
}
// NewOCISHandler implements a glauth backend with ocis-accounts as the datasource
func NewOCISHandler(opts ...Option) handler.Handler {
options := newOptions(opts...)
handler := ocisHandler{
log: options.Logger,
cfg: options.Config,
as: options.AccountsService,
gs: options.GroupsService,
log: options.Logger,
as: options.AccountsService,
gs: options.GroupsService,
basedn: options.BaseDN,
nameFormat: options.NameFormat,
groupFormat: options.GroupFormat,
}
return handler
}

View File

@@ -15,7 +15,13 @@ type Option func(o *Options)
type Options struct {
Logger log.Logger
Context context.Context
Config *config.Config
LDAP *config.LDAP
LDAPS *config.LDAPS
Backend *config.Config
Fallback *config.Config
BaseDN string
NameFormat string
GroupFormat string
AccountsService accounts.AccountsService
GroupsService accounts.GroupsService
}
@@ -45,10 +51,52 @@ func Context(val context.Context) Option {
}
}
// Config provides a function to set the config option.
func Config(val *config.Config) Option {
// LDAP provides a function to set the LDAP option.
func LDAP(val *config.LDAP) Option {
return func(o *Options) {
o.Config = val
o.LDAP = val
}
}
// LDAPS provides a function to set the LDAPS option.
func LDAPS(val *config.LDAPS) Option {
return func(o *Options) {
o.LDAPS = val
}
}
// Backend provides a function to set the backend option.
func Backend(val *config.Config) Option {
return func(o *Options) {
o.Backend = val
}
}
// Fallback provides a strring to set the fallback option.
func Fallback(val *config.Config) Option {
return func(o *Options) {
o.Fallback = val
}
}
// BaseDN provides a strring to set the BaseDN option.
func BaseDN(val string) Option {
return func(o *Options) {
o.BaseDN = val
}
}
// NameFormat provides a strring to set the NameFormat option.
func NameFormat(val string) Option {
return func(o *Options) {
o.NameFormat = val
}
}
// GroupFormat provides a strring to set the GroupFormat option.
func GroupFormat(val string) Option {
return func(o *Options) {
o.GroupFormat = val
}
}

View File

@@ -15,7 +15,10 @@ import (
// LdapSvc holds the ldap server struct
type LdapSvc struct {
log logr.Logger
c *config.Config
ldap *config.LDAP
ldaps *config.LDAPS
backend *config.Config
fallback *config.Config
yubiAuth *yubigo.YubiAuth
l *ldap.Server
}
@@ -26,14 +29,17 @@ func Server(opts ...Option) (*LdapSvc, error) {
options := newOptions(opts...)
s := LdapSvc{
log: mlogr.New(&options.Logger),
c: options.Config,
log: mlogr.New(&options.Logger),
backend: options.Backend,
fallback: options.Fallback,
ldap: options.LDAP,
ldaps: options.LDAPS,
}
var err error
if len(s.c.YubikeyClientID) > 0 && len(s.c.YubikeySecret) > 0 {
s.yubiAuth, err = yubigo.NewYubiAuth(s.c.YubikeyClientID, s.c.YubikeySecret)
if len(s.backend.YubikeyClientID) > 0 && len(s.backend.YubikeySecret) > 0 {
s.yubiAuth, err = yubigo.NewYubiAuth(s.backend.YubikeyClientID, s.backend.YubikeySecret)
if err != nil {
return nil, errors.New("yubikey auth failed")
@@ -43,58 +49,101 @@ func Server(opts ...Option) (*LdapSvc, error) {
// configure the backend
s.l = ldap.NewServer()
s.l.EnforceLDAP = true
var h handler.Handler
switch s.c.Backend.Datastore {
var bh handler.Handler
switch s.backend.Backend.Datastore {
/* TODO bring back file config
case "config":
h = handler.NewConfigHandler(
bh = handler.NewConfigHandler(
handler.Logger(s.log),
handler.Config(s.c),
handler.YubiAuth(s.yubiAuth),
)
*/
case "ldap":
h = handler.NewLdapHandler(
bh = handler.NewLdapHandler(
handler.Logger(s.log),
handler.Config(s.c),
handler.Config(s.backend),
)
case "owncloud":
h = handler.NewOwnCloudHandler(
bh = handler.NewOwnCloudHandler(
handler.Logger(s.log),
handler.Config(s.c),
handler.Config(s.backend),
)
case "accounts":
h = NewOCISHandler(
bh = NewOCISHandler(
AccountsService(options.AccountsService),
GroupsService(options.GroupsService),
Logger(options.Logger),
Config(s.c),
BaseDN(s.backend.Backend.BaseDN),
NameFormat(s.backend.Backend.NameFormat),
GroupFormat(s.backend.Backend.GroupFormat),
)
default:
return nil, fmt.Errorf("unsupported backend %s - must be 'ldap', 'owncloud' or 'accounts'", s.c.Backend.Datastore)
//return nil, fmt.Errorf("unsupported backend %s - must be 'config', 'homed', 'ldap', 'owncloud' or 'accounts'", s.c.Backend.Datastore)
return nil, fmt.Errorf("unsupported backend %s - must be 'ldap', 'owncloud' or 'accounts'", s.backend.Backend.Datastore)
}
s.log.V(3).Info("Using backend", "datastore", s.c.Backend.Datastore)
s.l.BindFunc(s.c.Backend.BaseDN, h)
s.l.SearchFunc(s.c.Backend.BaseDN, h)
s.l.CloseFunc(s.c.Backend.BaseDN, h)
s.log.V(3).Info("Using backend", "backend", s.backend.Backend)
if s.fallback != nil && s.fallback.Backend.Datastore != "" {
var fh handler.Handler
switch s.fallback.Backend.Datastore {
/* TODO bring back file config
case "config":
fh = handler.NewConfigHandler(
handler.Logger(s.log),
handler.Config(s.c),
handler.YubiAuth(s.yubiAuth),
)
*/
case "ldap":
fh = handler.NewLdapHandler(
handler.Logger(s.log),
handler.Config(s.fallback),
)
case "owncloud":
fh = handler.NewOwnCloudHandler(
handler.Logger(s.log),
handler.Config(s.fallback),
)
case "accounts":
fh = NewOCISHandler(
AccountsService(options.AccountsService),
GroupsService(options.GroupsService),
Logger(options.Logger),
BaseDN(s.fallback.Backend.BaseDN),
NameFormat(s.fallback.Backend.NameFormat),
GroupFormat(s.fallback.Backend.GroupFormat),
)
default:
return nil, fmt.Errorf("unsupported fallback %s - must be 'ldap', 'owncloud' or 'accounts'", s.fallback.Backend.Datastore)
}
s.log.V(3).Info("Using fallback", "backend", s.fallback.Backend)
bh = NewChainHandler(options.Logger, bh, fh)
}
s.l.BindFunc(s.backend.Backend.BaseDN, bh)
s.l.SearchFunc(s.backend.Backend.BaseDN, bh)
s.l.CloseFunc(s.backend.Backend.BaseDN, bh)
return &s, nil
}
// ListenAndServe listens on the TCP network address s.c.LDAP.Listen
func (s *LdapSvc) ListenAndServe() error {
s.log.V(3).Info("LDAP server listening", "address", s.c.LDAP.Listen)
return s.l.ListenAndServe(s.c.LDAP.Listen)
s.log.V(3).Info("LDAP server listening", "address", s.ldap.Listen)
return s.l.ListenAndServe(s.ldap.Listen)
}
// ListenAndServeTLS listens on the TCP network address s.c.LDAPS.Listen
func (s *LdapSvc) ListenAndServeTLS() error {
s.log.V(3).Info("LDAPS server listening", "address", s.c.LDAPS.Listen)
s.log.V(3).Info("LDAPS server listening", "address", s.ldaps.Listen)
return s.l.ListenAndServeTLS(
s.c.LDAPS.Listen,
s.c.LDAPS.Cert,
s.c.LDAPS.Key,
s.ldaps.Listen,
s.ldaps.Cert,
s.ldaps.Key,
)
}

View File

@@ -5,18 +5,18 @@ go 1.13
require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1
contrib.go.opencensus.io/exporter/ocagent v0.7.0
contrib.go.opencensus.io/exporter/zipkin v0.1.1
contrib.go.opencensus.io/exporter/zipkin v0.1.2
github.com/UnnoTed/fileb0x v1.1.4
github.com/go-test/deep v1.0.6 // indirect
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/micro/cli/v2 v2.1.2
github.com/micro/micro/v2 v2.8.0
github.com/openzipkin/zipkin-go v0.2.2
github.com/openzipkin/zipkin-go v0.2.5
github.com/owncloud/flaex v0.2.0
github.com/owncloud/ocis-graph v0.0.0-20200318175820-9a5a6e029db7
github.com/owncloud/ocis-graph-explorer v0.0.0-20200210111049-017eeb40dc0c
github.com/owncloud/ocis-hello v0.1.0-alpha1.0.20200828085053-37fcf3c8f853
github.com/owncloud/ocis-migration v0.2.0 // indirect
github.com/owncloud/ocis-proxy v0.7.1-0.20200907105449-201b9a652685 // indirect
github.com/owncloud/ocis/accounts v0.4.2-0.20200901074457-6a27781a2741
github.com/owncloud/ocis/accounts v0.5.2
github.com/owncloud/ocis/glauth v0.0.0-00010101000000-000000000000
github.com/owncloud/ocis/konnectd v0.0.0-00010101000000-000000000000
github.com/owncloud/ocis/ocis-phoenix v0.0.0-00010101000000-000000000000

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,10 @@ func GLAuthCommand(cfg *config.Config) *cli.Command {
Category: "Extensions",
Flags: flagset.ServerWithConfig(cfg.GLAuth),
Action: func(c *cli.Context) error {
cfg.GLAuth.Backend.Servers = c.StringSlice("backend-server")
cfg.GLAuth.Fallback.Servers = c.StringSlice("fallback-server")
scfg := configureGLAuth(cfg)
return cli.HandleAction(