From 83d69b99312884ad9f56caa3b3677b1c5e22e859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=B6ller?= Date: Sat, 9 Mar 2024 12:11:56 +0100 Subject: [PATCH] Add Auth (Gamma 2.0) support --- README.md | 60 +++++++++++--------- docker-compose.yml | 14 +++++ example.config.toml | 58 ++++++++++--------- internal/app/cli/services.go | 8 ++- internal/app/web/services.go | 5 ++ internal/pkg/services/auth/service.go | 81 +++++++++++++++++++++++++++ prod.docker-compose.yaml | 23 ++++---- 7 files changed, 186 insertions(+), 63 deletions(-) create mode 100644 internal/pkg/services/auth/service.go diff --git a/README.md b/README.md index 8a926a1..5480075 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,34 @@ -# GoldApps +# GoldApps + A system for syncing LDAP with gsuite and json files written in Go ### Features -* Migrate groups (from -> to): - * ldap -> gapps - * ldap -> json - * gapps -> json - * gapps -> gapps - * json -> gapps - * (json -> json) + +- Migrate groups (from -> to): + - ldap -> gapps + - ldap -> json + - gapps -> json + - gapps -> gapps + - json -> gapps + - (json -> json) + +## Dummy setup + +Create the following files: + +- `config.toml` - Copy from example.config.toml +- `gapps.json` - Containing `{}` +- `additions.json` - Containing `{}` +- `gamma.json` - Containing `{}` ## Setup -* Copy example.config.toml to config.toml and edit -* Grabb gapps.json and place in working directory - * go to [Google developer console](https://console.developers.google.com) - * go to credentials - * create new service account för this app - * use the downloaded file + +- Copy example.config.toml to config.toml and edit +- Grabb gapps.json and place in working directory + - go to [Google developer console](https://console.developers.google.com) + - go to credentials + - create new service account för this app + - use the downloaded file ## Usage @@ -30,19 +42,17 @@ For some reason `entrypoint` has to be specified in the compose file or the dock The command should be your flags for the `goldapps` command -See `prod.docker-compose.yaml` as reference. - ### Command `goldapps` The following flags are available: -* `-y`: No interacting from the user required. -* `-i`: Ask the user about everything... -* `-dry`: Makes sure the program does not change anything. -* `-from someString`: Set the group source to `ldap`, `gapps` or `*.json`. In case of `gapps` config value `gapps.provider` will be used. -* `-to someString`: Set the group consumer to 'gapps' or '*.json'. In case of `gapps` config value `gapps.consumer` will be used. -* `-users`: Only collect and sync users -* `-groups`: Only collect and sync groups -* `-additions *.json`: file with additions +- `-y`: No interacting from the user required. +- `-i`: Ask the user about everything... +- `-dry`: Makes sure the program does not change anything. +- `-from someString`: Set the group source to `ldap`, `gapps` or `*.json`. In case of `gapps` config value `gapps.provider` will be used. +- `-to someString`: Set the group consumer to 'gapps' or '\*.json'. In case of `gapps` config value `gapps.consumer` will be used. +- `-users`: Only collect and sync users +- `-groups`: Only collect and sync groups +- `-additions *.json`: file with additions -Notice that flags should be combined on the form `goldapps -a -b` and **NOT** on the form `goldapps -ab`. \ No newline at end of file +Notice that flags should be combined on the form `goldapps -a -b` and **NOT** on the form `goldapps -ab`. diff --git a/docker-compose.yml b/docker-compose.yml index c506b3e..8890e96 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,8 @@ services: POSTGRES_USER: user POSTGRES_DB: postgres POSTGRES_PASSWORD: password + networks: + - gamma-internal gamma-frontend: image: cthit/gamma-frontend:development @@ -13,6 +15,8 @@ services: HTTP_PROXY: http://gamma-backend:8081 ports: - 3000:3000 + networks: + - gamma-internal gamma-backend: # Starta med cthit/gamma-backend:development för att få in mock data @@ -43,6 +47,16 @@ services: - ./mock.json:/mock/mock.json ports: - 8081:8081 + networks: + - gamma + - gamma-internal redis: image: redis:5.0 + networks: + - gamma-internal + +networks: + gamma: + external: True + gamma-internal: \ No newline at end of file diff --git a/example.config.toml b/example.config.toml index 1049d72..c7ecf6d 100644 --- a/example.config.toml +++ b/example.config.toml @@ -1,48 +1,52 @@ [gapps.consumer] - servicekeyfile = "gapps.json" - adminaccount = "admin@mydomain.ex" +servicekeyfile = "gapps.json" +adminaccount = "admin@mydomain.ex" [gapps.provider] - servicekeyfile = "gapps.json" - adminaccount = "admin@mydomain.ex" +servicekeyfile = "gapps.json" +adminaccount = "admin@mydomain.ex" [gamma.provider] - apiKey = "key" - url = "http://localhost:8081" +apiKey = "key" +url = "http://gamma-backend:8081" + +[auth.provider] +apiKey = "key" +url = "http://gamma-mock:8081" [additions] file = "additions.json" [ldap] - url = "ldap.mydomain.ex:636" - servername = "mydomain.ex" - user = "cn=admin,dc=mydomain,dc=ex" - password = "PASSWORD" - custom = ["fkit", "kit"] +url = "ldap.mydomain.ex:636" +servername = "mydomain.ex" +user = "cn=admin,dc=mydomain,dc=ex" +password = "PASSWORD" +custom = ["fkit", "kit"] [ldap.groups] - basedn = "ou=groups,dc=mydomain,dc=ex" - filter = "(|(objectClass=itGroup)(objectClass=itPosition))" - attibutes = ["cn", "displayName", "mail", "member"] +basedn = "ou=groups,dc=mydomain,dc=ex" +filter = "(|(objectClass=itGroup)(objectClass=itPosition))" +attibutes = ["cn", "displayName", "mail", "member"] [ldap.users] - basedn = "ou=people,dc=mydomain,dc=ex" - filter = "(&(objectClass=chalmersstudent))" - attibutes = ["uid", "mail"] +basedn = "ou=people,dc=mydomain,dc=ex" +filter = "(&(objectClass=chalmersstudent))" +attibutes = ["uid", "mail"] #### CUSTOM FILTERS #### [ldap.fkit] - mail = "fkit@mydomain.ex" - basedn = "ou=fkit,ou=groups,dc=mydomain,dc=ex" - filter = "(&(objectClass=itGroup))" - parent_filter = "(&(ou=%childRDN%))" - attibutes = ["cn", "displayName", "mail"] +mail = "fkit@mydomain.ex" +basedn = "ou=fkit,ou=groups,dc=mydomain,dc=ex" +filter = "(&(objectClass=itGroup))" +parent_filter = "(&(ou=%childRDN%))" +attibutes = ["cn", "displayName", "mail"] [ldap.kit] - mail = "kit@mydomain.ex" - basedn = "ou=fkit,ou=groups,dc=mydomain,dc=ex" - filter = "(&(objectClass=itGroup)(type=Committee))" - parent_filter = "(&(ou=%childRDN%))" - attibutes = ["cn", "displayName", "mail"] +mail = "kit@mydomain.ex" +basedn = "ou=fkit,ou=groups,dc=mydomain,dc=ex" +filter = "(&(objectClass=itGroup)(type=Committee))" +parent_filter = "(&(ou=%childRDN%))" +attibutes = ["cn", "displayName", "mail"] #### ============== #### diff --git a/internal/app/cli/services.go b/internal/app/cli/services.go index cf83755..1cd924d 100644 --- a/internal/app/cli/services.go +++ b/internal/app/cli/services.go @@ -7,6 +7,7 @@ import ( "github.com/cthit/goldapps/internal/pkg/model" "github.com/cthit/goldapps/internal/pkg/services" "github.com/cthit/goldapps/internal/pkg/services/admin" + "github.com/cthit/goldapps/internal/pkg/services/auth" "github.com/cthit/goldapps/internal/pkg/services/gamma" "github.com/cthit/goldapps/internal/pkg/services/json" "github.com/cthit/goldapps/internal/pkg/services/ldap" @@ -80,7 +81,12 @@ func getProvider() services.CollectionService { panic(err) } return provider - + case "auth": + provider, _ := auth.CreateAuthService( + viper.GetString("auth.provider.apiKey"), + viper.GetString("auth.provider.url"), + ) + return provider default: isJson, _ := regexp.MatchString(`.+\.json$`, from) if isJson { diff --git a/internal/app/web/services.go b/internal/app/web/services.go index ec463a0..f4657f7 100644 --- a/internal/app/web/services.go +++ b/internal/app/web/services.go @@ -11,6 +11,7 @@ import ( "github.com/cthit/goldapps/internal/pkg/model" "github.com/cthit/goldapps/internal/pkg/services" "github.com/cthit/goldapps/internal/pkg/services/admin" + "github.com/cthit/goldapps/internal/pkg/services/auth" "github.com/cthit/goldapps/internal/pkg/services/gamma" "github.com/cthit/goldapps/internal/pkg/services/json" "github.com/spf13/viper" @@ -48,6 +49,10 @@ func getProvider(fromJson string) (services.CollectionService, error) { provider, err = gamma.CreateGammaService( viper.GetString("gamma.provider.apiKey"), viper.GetString("gamma.provider.url")) + } else if fromJson == "auth" { + provider, _ = auth.CreateAuthService( + viper.GetString("auth.provider.apiKey"), + viper.GetString("auth.provider.url")) } else if isJson { provider, err = json.NewJsonService(fromJson) } else { diff --git a/internal/pkg/services/auth/service.go b/internal/pkg/services/auth/service.go new file mode 100644 index 0000000..7814286 --- /dev/null +++ b/internal/pkg/services/auth/service.go @@ -0,0 +1,81 @@ +package auth + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + + "github.com/cthit/goldapps/internal/pkg/model" +) + +type AuthService struct { + apiKey string + url string +} + +//Creates a auth service which has the url to auth and the pre-shared key +func CreateAuthService(apiKey string, url string) (AuthService, error) { + return AuthService{ + apiKey: apiKey, + url: url, + }, nil +} + +//Executes a generic get request with api key +func request(s *AuthService, endpoint string, response interface{}) error { + req, err := http.NewRequest("GET", fmt.Sprintf("%s%s", s.url, endpoint), nil) + if err != nil { + log.Println(err) + return err + } + + req.Header.Set("Authorization", fmt.Sprintf("pre-shared %s", s.apiKey)) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Println(err) + return err + } + fmt.Printf("Request sent to: %s [key: %s] status %d\n", endpoint, s.apiKey, resp.StatusCode) + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println(err) + return err + } + + err = json.Unmarshal(body, &response) + if err != nil { + log.Println(err) + return err + } + + return nil +} + +func (s AuthService) GetGroups() ([]model.Group, error) { + var groups []model.Group + + err := request(&s, "/api/goldapps/groups", &groups) + if err != nil { + log.Println(err) + return nil, err + } + + return groups, nil +} + +func (s AuthService) GetUsers() ([]model.User, error) { + var users []model.User + + err := request(&s, "/api/goldapps/users", &users) + if err != nil { + log.Println(err) + return nil, err + } + + return users, nil +} diff --git a/prod.docker-compose.yaml b/prod.docker-compose.yaml index 500ee21..da6db75 100644 --- a/prod.docker-compose.yaml +++ b/prod.docker-compose.yaml @@ -5,28 +5,23 @@ services: dockerfile: Dockerfile context: . image: goldapps:stable - network_mode: host # Easier since gamma is running with a different docker-compose - command: [ - "-from ldap", - "-to gapps", - "-additions additions.json", - "-y", - "-dry" - ] volumes: - ./config.toml:/app/config.toml:ro - ./gapps.json:/app/gapps.json:ro - ./additions.json:/app/additions.json:ro + - ./gamma.json:/app/gamma.json:ro + networks: + - gamma web: build: dockerfile: Dockerfile.web context: . - network_mode: host # Easier since gamma is running with a different docker-compose volumes: - ./config.toml:/app/config.toml:ro - ./gapps.json:/app/gapps.json:ro - ./additions.json:/app/additions.json:ro + - ./gamma.json:/app/gamma.json:ro environment: GIN_MODE: debug SESSION_SECRET: secret @@ -36,4 +31,12 @@ services: # Gamma client info GAMMA_CLIENT_ID: id GAMMA_CLIENT_SECRET: key - GAMMA_REDIRECT_URL: http://localhost:3001/callback + GAMMA_REDIRECT_URL: http://localhost:8080/api/authenticate + networks: + - gamma + ports: + - 8080:8080 + +networks: + gamma: + external: True \ No newline at end of file