diff --git a/go.mod b/go.mod index ff2a28d3a..4d447b759 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,14 @@ require ( github.com/cespare/reflex v0.2.0 // indirect github.com/go-chi/chi v4.0.2+incompatible github.com/go-chi/render v1.0.1 + github.com/haya14busa/goverage v0.0.0-20180129164344-eec3514a20b5 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/micro/cli v0.2.0 github.com/ogier/pflag v0.0.1 // indirect github.com/oklog/run v1.0.0 github.com/openzipkin/zipkin-go v0.2.2 - github.com/owncloud/ocis-pkg v1.1.0 + github.com/owncloud/ocis-pkg v1.2.1-0.20191216110718-ef1320072cd7 + github.com/restic/calens v0.1.0 // indirect github.com/spf13/viper v1.5.0 github.com/yaegashi/msgraph.go v0.0.0-20191104022859-3f9096c750b2 go.opencensus.io v0.22.2 diff --git a/go.sum b/go.sum index f004128d1..b95550bd2 100644 --- a/go.sum +++ b/go.sum @@ -145,6 +145,8 @@ github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.17+incompatible h1:f/Z3EoDSx1yjaIjLQGo1diYUlQYSBrrAQ5vP8NjwXwo= github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -520,6 +522,15 @@ github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukw github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= github.com/owncloud/ocis-pkg v1.1.0 h1:cwhzqQAHLA8fz94YKdmqSJguSCswx5TBNkgLAU8DbJI= github.com/owncloud/ocis-pkg v1.1.0/go.mod h1:EfbeXoe60Me2lB/AWjYl8UFNv4isqCPP6lokd5R7nyM= +github.com/owncloud/ocis-pkg v1.2.0 h1:eP0AOSEXAgiblL2yOpNOmriKhDXN+mai+4belBJRkWU= +github.com/owncloud/ocis-pkg v1.2.1-0.20191210134105-b9281c88fa4e h1:/ZEn35TnY4Xv7VKRN43Tb5NVgt6CeYPMw5akFKB01u4= +github.com/owncloud/ocis-pkg v1.2.1-0.20191210134105-b9281c88fa4e/go.mod h1:YbsEi4rWRqnDpN1U8MDJ6Ys+cWn2lskTYgyKgOmCrFk= +github.com/owncloud/ocis-pkg v1.2.1-0.20191211143857-ab52855478bf h1:1uKK2HSeEtvK2CshhwAMFIzJLTTyd0rh2f90n3rqTqw= +github.com/owncloud/ocis-pkg v1.2.1-0.20191211143857-ab52855478bf/go.mod h1:YbsEi4rWRqnDpN1U8MDJ6Ys+cWn2lskTYgyKgOmCrFk= +github.com/owncloud/ocis-pkg v1.2.1-0.20191216100329-ca11e16505c6 h1:3kKO/aMzV+2aIYBvBgbzCuciUZxiYV7QxR9s525B9Dw= +github.com/owncloud/ocis-pkg v1.2.1-0.20191216100329-ca11e16505c6/go.mod h1:YbsEi4rWRqnDpN1U8MDJ6Ys+cWn2lskTYgyKgOmCrFk= +github.com/owncloud/ocis-pkg v1.2.1-0.20191216110718-ef1320072cd7 h1:aLFn8VM6u/2TOy6JEMP1D/09ceNr0isZ3LhegSmLVns= +github.com/owncloud/ocis-pkg v1.2.1-0.20191216110718-ef1320072cd7/go.mod h1:YbsEi4rWRqnDpN1U8MDJ6Ys+cWn2lskTYgyKgOmCrFk= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -540,6 +551,8 @@ github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6J github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -754,6 +767,7 @@ golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -906,6 +920,7 @@ gopkg.in/olivere/elastic.v5 v5.0.82/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0F gopkg.in/redis.v3 v3.6.4/go.mod h1:6XeGv/CrsUFDU9aVbUdNykN7k1zVmoeg83KC9RbQfiU= gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= diff --git a/pkg/config/config.go b/pkg/config/config.go index 2d5b2cf97..902754e98 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -40,14 +40,23 @@ type Ldap struct { BaseDNGroups string } +// OpenIDConnect defined the avialable OpenID Connect configuration. +type OpenIDConnect struct { + Endpoint string + Realm string + SigningAlgs []string + Insecure bool +} + // Config combines all available configuration parts. type Config struct { - File string - Log Log - Debug Debug - HTTP HTTP - Tracing Tracing - Ldap Ldap + File string + Log Log + Debug Debug + HTTP HTTP + Tracing Tracing + Ldap Ldap + OpenIDConnect OpenIDConnect } // New initializes a new configuration with or without defaults. diff --git a/pkg/flagset/flagset.go b/pkg/flagset/flagset.go index e70ad23fd..240aa04ab 100644 --- a/pkg/flagset/flagset.go +++ b/pkg/flagset/flagset.go @@ -169,5 +169,25 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVar: "GRAPH_LDAP_BASEDN_GROUPS", Destination: &cfg.Ldap.BaseDNGroups, }, + &cli.StringFlag{ + Name: "oidc-endpoint", + Value: "", + Usage: "OpenIDConnect endpoint", + EnvVar: "GRAPH_OIDC_ENDPOINT", + Destination: &cfg.OpenIDConnect.Endpoint, + }, + &cli.BoolFlag{ + Name: "oidc-insecure", + Usage: "OpenIDConnect endpoint", + EnvVar: "GRAPH_OIDC_INSECURE", + Destination: &cfg.OpenIDConnect.Insecure, + }, + &cli.StringFlag{ + Name: "oidc-realm", + Value: "", + Usage: "OpenIDConnect realm", + EnvVar: "GRAPH_OIDC_REALM", + Destination: &cfg.OpenIDConnect.Realm, + }, } } diff --git a/pkg/server/http/server.go b/pkg/server/http/server.go index ae2d645af..b04bbaf2d 100644 --- a/pkg/server/http/server.go +++ b/pkg/server/http/server.go @@ -4,6 +4,7 @@ import ( svc "github.com/owncloud/ocis-graph/pkg/service/v0" "github.com/owncloud/ocis-graph/pkg/version" "github.com/owncloud/ocis-pkg/middleware" + "github.com/owncloud/ocis-pkg/oidc" "github.com/owncloud/ocis-pkg/service/http" ) @@ -37,6 +38,12 @@ func Server(opts ...Option) (http.Service, error) { middleware.Logger( options.Logger, ), + middleware.OpenIDConnect( + oidc.Endpoint(options.Config.OpenIDConnect.Endpoint), + oidc.Realm(options.Config.OpenIDConnect.Realm), + oidc.Insecure(options.Config.OpenIDConnect.Insecure), + oidc.Logger(options.Logger), + ), ), ) diff --git a/pkg/service/v0/graph.go b/pkg/service/v0/graph.go index cb1b9f7fd..3eb4ad8d7 100644 --- a/pkg/service/v0/graph.go +++ b/pkg/service/v0/graph.go @@ -2,7 +2,6 @@ package svc import ( "context" - "encoding/json" "errors" "fmt" "net/http" @@ -13,6 +12,7 @@ import ( "github.com/go-chi/render" "github.com/owncloud/ocis-graph/pkg/config" "github.com/owncloud/ocis-pkg/log" + "github.com/owncloud/ocis-pkg/oidc" msgraph "github.com/yaegashi/msgraph.go/v1.0" ldap "gopkg.in/ldap.v3" ) @@ -42,7 +42,8 @@ func (g Graph) UserCtx(next http.Handler) http.Handler { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest) return } - user, err = g.ldapGetSingleEntry(userID, g.config.Ldap.BaseDNUsers) + filter := fmt.Sprintf("(entryuuid=%s)", userID) + user, err = g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter) if err != nil { g.logger.Info().Err(err).Msgf("Failed to read user %s", userID) errorcode.ItemNotFound.Render(w, r, http.StatusNotFound) @@ -64,7 +65,8 @@ func (g Graph) GroupCtx(next http.Handler) http.Handler { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest) return } - group, err := g.ldapGetSingleEntry(groupID, g.config.Ldap.BaseDNGroups) + filter := fmt.Sprintf("(entryuuid=%s)", groupID) + group, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNGroups, filter) if err != nil { g.logger.Info().Err(err).Msgf("Failed to read group %s", groupID) errorcode.ItemNotFound.Render(w, r, http.StatusNotFound) @@ -78,21 +80,21 @@ func (g Graph) GroupCtx(next http.Handler) http.Handler { // GetMe implements the Service interface. func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) { - me := createUserModel( - "Alice", - "1234-5678-9000-000", - ) - - resp, err := json.Marshal(me) + claims := oidc.FromContext(r.Context()) + g.logger.Info().Interface("Claims", claims).Msg("Claims in /me") + filter := fmt.Sprintf("(uid=%s)", claims.PreferredUsername) + user, err := g.ldapGetSingleEntry(g.config.Ldap.BaseDNUsers, filter) if err != nil { - g.logger.Error().Err(err).Msgf("Failed to marshal object %s", me) - errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError) + g.logger.Info().Err(err).Msgf("Failed to read user %s", claims.PreferredUsername) + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound) return } + me := createUserModelFromLDAP(user) + render.Status(r, http.StatusOK) - render.JSON(w, r, resp) + render.JSON(w, r, me) } // GetUsers implements the Service interface. @@ -175,12 +177,11 @@ func (g Graph) GetGroup(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, createGroupModelFromLDAP(group)) } -func (g Graph) ldapGetSingleEntry(resourceID string, baseDn string) (*ldap.Entry, error) { +func (g Graph) ldapGetSingleEntry(baseDn string, filter string) (*ldap.Entry, error) { conn, err := g.initLdap() if err != nil { return nil, err } - filter := fmt.Sprintf("(entryuuid=%s)", resourceID) result, err := g.ldapSearch(conn, filter, baseDn) if err != nil { return nil, err @@ -229,18 +230,6 @@ func (g Graph) ldapSearch(con *ldap.Conn, filter string, baseDN string) (*ldap.S return con.Search(search) } -func createUserModel(displayName string, id string) *msgraph.User { - return &msgraph.User{ - DisplayName: &displayName, - GivenName: &displayName, - DirectoryObject: msgraph.DirectoryObject{ - Entity: msgraph.Entity{ - ID: &id, - }, - }, - } -} - func createUserModelFromLDAP(entry *ldap.Entry) *msgraph.User { displayName := entry.GetAttributeValue("displayname") givenName := entry.GetAttributeValue("givenname") diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index 0ecf2f58f..c49e0e0cb 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -29,6 +29,7 @@ func NewService(opts ...Option) Service { m.Route(options.Config.HTTP.Root, func(r chi.Router) { r.Route("/v1.0", func(r chi.Router) { + r.Get("/me", svc.GetMe) r.Route("/users", func(r chi.Router) { r.Get("/", svc.GetUsers) r.Route("/{userID}", func(r chi.Router) { diff --git a/reflex.conf b/reflex.conf index 6b47c0a2a..32c48e4c4 100644 --- a/reflex.conf +++ b/reflex.conf @@ -1,2 +1,2 @@ # backend --r '^(cmd|pkg)/.*\.go$' -R '^node_modules/' -s -- sh -c 'make bin/ocis-graph-debug && bin/ocis-graph-debug --log-level debug server --debug-pprof --debug-zpages' +-r '^(cmd|pkg)/.*\.go$' -R '^node_modules/' -s -- sh -c 'make bin/ocis-graph-debug && bin/ocis-graph-debug --log-level debug server --debug-pprof --debug-zpages --oidc-endpoint="https://deepdiver" --oidc-insecure=1'