Skip to content

Commit 1a731d4

Browse files
committed
refactor: use gitea sdk
feat: add user sync Signed-off-by: Janos Miko <mixe3y@gmail.com>
1 parent 04930ae commit 1a731d4

File tree

15 files changed

+739
-1145
lines changed

15 files changed

+739
-1145
lines changed

.github/workflows/docker-publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ jobs:
2222
- name: Build
2323
run: |-
2424
docker build \
25-
--tag "ghcr.io/janosmiko/gitea-group-sync:latest" \
25+
--tag "ghcr.io/janosmiko/gitea-ldap-sync:latest" \
2626
.
2727
2828
- name: Publish
2929
run: |-
30-
docker push "ghcr.io/janosmiko/gitea-group-sync:latest"
30+
docker push "ghcr.io/janosmiko/gitea-ldap-sync:latest"

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
FROM golang:1.17.8-bullseye AS build
22

3-
WORKDIR /go/src/github.com/janosmiko/gitea-group-sync/
3+
WORKDIR /go/src/github.com/janosmiko/gitea-ldap-sync/
44

55
COPY go.mod go.sum ./
66

77
RUN go mod download -x
88

99
COPY . ./
1010

11-
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o gitea-group-sync .
11+
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o gitea-ldap-sync .
1212

1313
FROM debian:bullseye-slim
1414

15-
COPY --from=build /go/src/github.com/janosmiko/gitea-group-sync/gitea-group-sync /usr/bin/gitea-group-sync
15+
COPY --from=build /go/src/github.com/janosmiko/gitea-ldap-sync/gitea-ldap-sync /usr/bin/gitea-ldap-sync
1616

1717
RUN apt-get update && apt-get install -y ca-certificates \
1818
&& rm -fr /var/cache/apt/
1919

20-
ENTRYPOINT ["/usr/bin/gitea-group-sync"]
20+
ENTRYPOINT ["/usr/bin/gitea-ldap-sync"]

README.md

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
# Gitea Group Sync from LDAP
1+
# Gitea Advanced LDAP User/Group Sync
22

3-
This application is designed to sync LDAP groups and user membership to Gitea.
3+
This application is designed to sync LDAP users, groups (orgs and teams) and user membership to Gitea.
44

55
It can do the following:
66

7+
- **Create** (and optionally delete) **Gitea Users** based on **LDAP users**.
78
- **Create** (and optionally delete) **Gitea Organizations** based on **LDAP groups**.
89
- **Create** (and optionally delete) **Gitea Teams** inside Organizations based on **LDAP subgroups**.
910
- **Attach** existing **Gitea Users** to appropriate **Gitea Teams** based on group membership information in LDAP.
1011

11-
**The application is not going to sync users from LDAP to Gitea as Gitea provides a solution for that.**
12+
~~The application is not going to sync users from LDAP to Gitea as Gitea provides a solution for that.~~
13+
14+
This application syncs users as well. We suggest to disable Gitea LDAP user sync (but you can still use Gitea's LDAP Provider).
1215

1316
Docker image available
14-
at [ghcr.io/janosmiko/gitea-group-sync](https://github.com/janosmiko/gitea-group-sync/pkgs/container/gitea-group-sync).
17+
at [ghcr.io/janosmiko/gitea-ldap-sync](https://github.com/janosmiko/gitea-ldap-sync/pkgs/container/gitea-ldap-sync).
1518

1619
## Usage
1720

@@ -25,7 +28,7 @@ docker-compose up -d
2528

2629
### Kubernetes
2730

28-
Modify the values in [deploy/secret.yaml](deploy/secret.yaml) and [deploy/job.yaml](deploy/job.yaml) and apply them to Kubernetes.
31+
Modify the values in [deploy/secret.yaml](deploy/secret.yaml) and [deploy/job.yaml](deploy/deployment.yaml) and apply them to Kubernetes.
2932

3033
```
3134
kubectl apply -f deploy/secret.yaml
@@ -39,34 +42,43 @@ Variables.
3942

4043
Available Environment Variables (find example values in [config.yaml.sample](config.yaml.sample)):
4144

42-
| Variable | Description | Default |
43-
|--------------------------------|------------------------------------------------------------|--------------------|
44-
| `DEBUG` | Enable debug mode | `false` |
45-
| `GITEA_BASE_URL` | Gitea baseURL in `https://user@gitea.com` format. | `""` |
46-
| `GITEA_TOKEN` | Gitea admin user token | `""` |
47-
| `LDAP_URL` | LDAP connection URL | `""` |
48-
| `LDAP_PORT` | LDAP connection port | `389` |
49-
| `LDAP_USE_TLS` | Enable TLS connection for LDAP | `true` |
50-
| `LDAP_ALLOW_INSECURE_TLS` | Allow insecure TLS connections (disable cert verification) | `false` |
51-
| `LDAP_BIND_DN` | LDAP Bind DN (or username) | `""` |
52-
| `LDAP_BIND_PASSWORD` | LDAP Bind Password | `""` |
53-
| `LDAP_USER_SEARCH_BASE` | LDAP User Search Base | `""` |
54-
| `LDAP_USER_FILTER` | LDAP User Filter | `""` |
55-
| `LDAP_USER_IDENTITY_ATTRIBUTE` | LDAP attribute to match Gitea User | `"sAMAccountName"` |
56-
| `LDAP_USER_FULLNAME` | LDAP attribute for Gitea User Fullname | `"cn"` |
57-
| `LDAP_GROUP_SEARCH_BASE` | LDAP Group Search Base (Gitea Organizations) | `""` |
58-
| `LDAP_GROUP_FILTER` | LDAP Group Filter | `""` |
59-
| `LDAP_SUBGROUP_SEARCH_BASE` | LDAP Subgroup Search Base (Gitea Teams) | `""` |
60-
| `LDAP_SUBGROUP_FILTER` | LDAP Subgroup filter | `""` |
61-
| `LDAP_EXCLUDE_GROUPS` | Exclude groups from sync (separated by whitespace) | `""` |
62-
| `LDAP_EXCLUDE_GROUPS_REGEX` | Exclude groups from sync (regular expression) | `""` |
63-
| `LDAP_EXCLUDE_SUBGROUPS` | Exclude subgroups from sync (separated by whitespace) | `""` |
64-
| `LDAP_EXCLUDE_SUBGROUPS_REGEX` | Exclude groups from sync (regular expression) | `""` |
65-
| `LDAP_TRIM_PARENT_NAME` | Trim parent name from subgroup name | `false` |
66-
| `LDAP_SUBGROUP_SEPARATOR` | Trim parent name from subgroup name by this separator | `"/"` |
67-
| `CRON_TIMER` | Configure the schedule of the sync (cron format) | `"@every 1m"` |
68-
| `SYNC_CONFIG_CREATE_GROUPS` | Create non-existing groups in Gitea. | `true` |
69-
| `SYNC_CONFIG_FULL_SYNC` | Delete groups from Gitea if they are not existing in LDAP | `false` |
45+
| Variable | Description | Default |
46+
|--------------------------------------|---------------------------------------------------------------|--------------------|
47+
| `DEBUG` | Enable debug mode | `false` |
48+
| `GITEA_BASE_URL` | Gitea baseURL in `https://user@gitea.com` format. | `""` |
49+
| `GITEA_TOKEN` | Gitea admin user token | `""` |
50+
| `LDAP_URL` | LDAP connection URL | `""` |
51+
| `LDAP_PORT` | LDAP connection port | `389` |
52+
| `LDAP_USE_TLS` | Enable TLS connection for LDAP | `true` |
53+
| `LDAP_ALLOW_INSECURE_TLS` | Allow insecure TLS connections (disable cert verification) | `false` |
54+
| `LDAP_BIND_DN` | LDAP Bind DN (or username) | `""` |
55+
| `LDAP_BIND_PASSWORD` | LDAP Bind Password | `""` |
56+
| `LDAP_USER_SEARCH_BASE` | LDAP User Search Base | `""` |
57+
| `LDAP_USER_FILTER` | LDAP User Filter | `""` |
58+
| `LDAP_USER_USERNAME_ATTRIBUTE` | LDAP attribute for Gitea User Username | `"sAMAccountName"` |
59+
| `LDAP_USER_FULLNAME_ATTRIBUTE` | LDAP attribute for Gitea User Fullname | `"cn"` |
60+
| `LDAP_USER_FIRST_NAME_ATTRIBUTE` | LDAP attribute for Gitea User First Name (first + sur = full) | `""` |
61+
| `LDAP_USER_SURNAME_ATTRIBUTE` | LDAP attribute for Gitea User Surname | `""` |
62+
| `LDAP_USER_EMAIL_ATTRIBUTE` | LDAP attribute for Gitea User Email | `"mail"` |
63+
| `LDAP_USER_PUBLIC_SSH_KEY_ATTRIBUTE` | LDAP attribute for Gitea User SSH Key | `"sshPublicKey"` |
64+
| `LDAP_USER_AVATAR_ATTRIBUTE` | LDAP attribute for Gitea User Avatar | `"avatar"` |
65+
| `LDAP_EXCLUDED_USERS` | Exclude users from sync (separated by whitespace) | `"root"` |
66+
| `LDAP_EXCLUDED_USERS_REGEX` | Exclude users from sync (regular expression) | `""` |
67+
| `LDAP_ADMIN_FILTER` | LDAP attribute for Gitea User Avatar | `""` |
68+
| `LDAP_RESTRICTED_FILTER` | LDAP attribute for Gitea User Avatar | `""` |
69+
| `LDAP_GROUP_SEARCH_BASE` | LDAP Group Search Base (Gitea Organizations) | `""` |
70+
| `LDAP_GROUP_FILTER` | LDAP Group Filter | `""` |
71+
| `LDAP_SUBGROUP_SEARCH_BASE` | LDAP Subgroup Search Base (Gitea Teams) | `""` |
72+
| `LDAP_SUBGROUP_FILTER` | LDAP Subgroup filter | `""` |
73+
| `LDAP_EXCLUDE_GROUPS` | Exclude groups from sync (separated by whitespace) | `""` |
74+
| `LDAP_EXCLUDE_GROUPS_REGEX` | Exclude groups from sync (regular expression) | `""` |
75+
| `LDAP_EXCLUDE_SUBGROUPS` | Exclude subgroups from sync (separated by whitespace) | `""` |
76+
| `LDAP_EXCLUDE_SUBGROUPS_REGEX` | Exclude groups from sync (regular expression) | `""` |
77+
| `LDAP_TRIM_PARENT_NAME` | Trim parent name from subgroup name | `false` |
78+
| `LDAP_SUBGROUP_SEPARATOR` | Trim parent name from subgroup name by this separator | `"/"` |
79+
| `CRON_TIMER` | Configure the schedule of the sync (cron format) | `"@every 1m"` |
80+
| `SYNC_CONFIG_CREATE_GROUPS` | Create non-existing groups in Gitea. | `true` |
81+
| `SYNC_CONFIG_FULL_SYNC` | Delete groups from Gitea if they are not existing in LDAP | `false` |
7082

7183

7284
Additional settings for creating Organizations and Teams in Gitea:
@@ -76,7 +88,6 @@ Additional settings for creating Organizations and Teams in Gitea:
7688
- `SYNC_CONFIG_DEFAULTS_TEAM_INCLUDES_ALL_REPOSITORIES`
7789
- `SYNC_CONFIG_DEFAULTS_TEAM_PERMISSION`
7890
- `SYNC_CONFIG_DEFAULTS_TEAM_UNITS`
79-
- `SYNC_CONFIG_DEFAULTS_TEAM_UNITS_MAP`
8091

8192
# License
8293

TODO.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# TODO
2+
3+
- add avatar sync, when it's available in Gitea SDK
4+
- add ssh public key sync, when it's available in Gitea SDK

config.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func initConfig() (*Config, error) {
1111
viper.AddConfigPath(".")
12-
viper.AddConfigPath("/etc/gitea-group-sync")
12+
viper.AddConfigPath("/etc/gitea-ldap-sync")
1313
viper.SetConfigName("config")
1414
viper.SetConfigType("yaml")
1515

@@ -20,19 +20,33 @@ func initConfig() (*Config, error) {
2020

2121
viper.SetTypeByDefaultValue(true)
2222
viper.SetDefault("gitea.token", []string{""})
23+
viper.SetDefault("ldap.exclude_users", []string{"root"})
2324
viper.SetDefault("ldap.exclude_groups", []string{""})
2425
viper.SetDefault("ldap.exclude_subgroups", []string{""})
2526
viper.SetDefault("gitea.client_timeout", 10) // nolint:gomnd
2627
viper.SetDefault("ldap.port", "389")
2728
viper.SetDefault("ldap.use_tls", true)
2829
viper.SetDefault("ldap.allow_insecure_tls", true)
29-
viper.SetDefault("ldap.user_identity_attribute", "sAMAccountName")
30-
viper.SetDefault("ldap.user_fullname", "cn")
30+
viper.SetDefault("ldap.user_username_attribute", "sAMAccountName")
31+
viper.SetDefault("ldap.user_fullname_attribute", "cn")
32+
viper.SetDefault("ldap.user_first_name_attribute", "name")
33+
viper.SetDefault("ldap.user_surname_attribute", "")
34+
viper.SetDefault("ldap.user_email_attribute", "mail")
35+
viper.SetDefault("ldap.user_public_ssh_key_attribute", "sshPublicKey")
36+
viper.SetDefault("ldap.user_avatar_attribute", "avatar")
37+
viper.SetDefault("ldap.admin_filter", "")
38+
viper.SetDefault("ldap.restricted_filter", "")
3139
viper.SetDefault("ldap.trim_parent_name", false)
3240
viper.SetDefault("ldap.subgroup_separator", "/")
41+
viper.SetDefault("ldap.exclude_users_regex", "")
42+
viper.SetDefault("ldap.exclude_groups_regex", "")
43+
viper.SetDefault("ldap.exclude_subgroups_regex", "")
3344
viper.SetDefault("cron_timer", "@every 1m")
3445
viper.SetDefault("sync_config.create_groups", true)
3546
viper.SetDefault("sync_config.full_sync", false)
47+
viper.SetDefault("sync_config.defaults.user.allow_create_organization", false)
48+
viper.SetDefault("sync_config.defaults.user.max_repo_creation", 0)
49+
viper.SetDefault("sync_config.defaults.user.visibility", "private")
3650
viper.SetDefault("sync_config.defaults.organization.repo_admin_change_team_access", false)
3751
viper.SetDefault("sync_config.defaults.organization.visibility", "private")
3852
viper.SetDefault("sync_config.defaults.team.can_create_org_repo", false)
@@ -50,11 +64,6 @@ func initConfig() (*Config, error) {
5064
"repo.ext_wiki"
5165
]`,
5266
)
53-
// nolint:lll
54-
viper.SetDefault(
55-
"sync_config.defaults.team.units_map",
56-
`{"repo.code":"write","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"write","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}`,
57-
)
5867

5968
_ = viper.BindEnv("gitea.base_url")
6069
_ = viper.BindEnv("gitea.token")
@@ -66,8 +75,14 @@ func initConfig() (*Config, error) {
6675
_ = viper.BindEnv("ldap.bind_password")
6776
_ = viper.BindEnv("ldap.user_filter")
6877
_ = viper.BindEnv("ldap.user_search_base")
69-
_ = viper.BindEnv("ldap.user_identity_attribute")
70-
_ = viper.BindEnv("ldap.user_fullname")
78+
_ = viper.BindEnv("ldap.user_username_attribute")
79+
_ = viper.BindEnv("ldap.user_fullname_attribute")
80+
_ = viper.BindEnv("ldap.user_first_name_attribute")
81+
_ = viper.BindEnv("ldap.user_surname_attribute")
82+
_ = viper.BindEnv("ldap.user_email_attribute")
83+
_ = viper.BindEnv("ldap.user_public_ssh_key_attribute")
84+
_ = viper.BindEnv("ldap.user_avatar_attribute")
85+
_ = viper.BindEnv("ldap.exclude_users")
7186
_ = viper.BindEnv("ldap.group_filter")
7287
_ = viper.BindEnv("ldap.group_search_base")
7388
_ = viper.BindEnv("ldap.subgroup_filter")
@@ -81,13 +96,15 @@ func initConfig() (*Config, error) {
8196
_ = viper.BindEnv("cron_timer")
8297
_ = viper.BindEnv("sync_config.create_groups")
8398
_ = viper.BindEnv("sync_config.full_sync")
99+
_ = viper.BindEnv("sync_config.defaults.user.allow_create_organization")
100+
_ = viper.BindEnv("sync_config.defaults.user.max_repo_creation")
101+
_ = viper.BindEnv("sync_config.defaults.user.visibility")
84102
_ = viper.BindEnv("sync_config.defaults.organization.repo_admin_change_team_access")
85103
_ = viper.BindEnv("sync_config.defaults.organization.visibility")
86104
_ = viper.BindEnv("sync_config.team.can_create_org_repo")
87105
_ = viper.BindEnv("sync_config.team.includes_all_repositories")
88106
_ = viper.BindEnv("sync_config.team.permission")
89107
_ = viper.BindEnv("sync_config.team.units")
90-
_ = viper.BindEnv("sync_config.team.units_map")
91108

92109
for _, v := range viper.AllKeys() {
93110
zap.S().Debug(v, ": ", viper.GetString(v))
@@ -135,10 +152,10 @@ func (c Config) checkConfig() {
135152
zap.L().Info("LDAP_USER_SEARCH_BASE is empty")
136153
missing = true
137154
}
138-
if len(c.LDAP.UserIdentityAttribute) == 0 {
139-
zap.L().Info("LDAP_USER_IDENTITY_ATTRIBUTE is empty, using default: 'sAMAccountName'")
155+
if len(c.LDAP.UserUsernameAttribute) == 0 {
156+
zap.L().Info("LDAP_USER_USERNAME_ATTRIBUTE is empty, using default: 'sAMAccountName'")
140157
}
141-
if len(c.LDAP.UserFullName) == 0 {
158+
if len(c.LDAP.UserFullNameAttribute) == 0 {
142159
zap.L().Info("LDAP_USER_FULLNAME is empty, using default: 'cn'")
143160
}
144161
if len(c.LDAP.GroupFilter) == 0 {

config.yaml.sample

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Example Configuration for gitea-group-sync
1+
# Example Configuration for gitea-ldap-sync
22
debug: false
33

44
# Gitea Configuration
@@ -20,8 +20,19 @@ ldap:
2020

2121
user_search_base: 'ou=users,DC=ldap,DC=example,DC=com'
2222
user_filter: '(&(objectClass=user)(memberOf=*))'
23-
user_identity_attribute: "sAMAccountName"
24-
user_fullname: "cn" # can be changed to "sn" if needed
23+
user_username_attribute: "sAMAccountName"
24+
user_fullname_attribute: "cn" # can be changed to "sn" if needed
25+
user_first_name_attribute: ""
26+
user_surname_attribute: ""
27+
user_email_attribute: "mail"
28+
user_public_ssh_key_attribute: "sshPublicKey"
29+
user_avatar_attribute: "avatar"
30+
31+
exclude_users: []
32+
exclude_users_regex: ""
33+
34+
admin_filter: ""
35+
restricted_filter: ""
2536

2637
# These groups will be mapped as Organizations in Gitea
2738
group_search_base: 'ou=groups,DC=ldap,DC=example,DC=com'
@@ -55,6 +66,9 @@ ldap:
5566
cron_timer: '@every 1m'
5667

5768
sync_config:
69+
# If CreateUsers is set to true, the process will create Users in Gitea.
70+
create_users: true
71+
5872
# If CreateGroups is set to true, the process will create Organizations and Teams in Gitea.
5973
create_groups: true
6074

@@ -64,6 +78,10 @@ sync_config:
6478

6579
# Default settings for creating Organizations and Teams in Gitea.
6680
defaults:
81+
user:
82+
allow_create_organization: false
83+
max_repo_creation: 0
84+
visibility: "private" # Valid options: private, limited, public
6785
organization:
6886
repo_admin_change_team_access: false
6987
visibility: "private"
@@ -82,4 +100,3 @@ sync_config:
82100
"repo.projects",
83101
"repo.ext_wiki"
84102
]
85-
units_map: '{"repo.code":"write","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"write","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}'

0 commit comments

Comments
 (0)