Skip to content

Commit b0b9141

Browse files
authored
Merge pull request #25 from GitGuardian/ybensafia/sync-gitlab-users
Synchronization script for Gitlab
2 parents 75a3297 + aba5042 commit b0b9141

File tree

7 files changed

+1190
-7
lines changed

7 files changed

+1190
-7
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ Should you have any inquiries or need assistance, please don't hesitate to conta
66

77
Below is a brief overview of the tools available in this repository:
88

9-
Tools | Description
10-
------------ | -------------
11-
[api-migration](./api-migration) | Facilitates the migration of incident remediation progress across different environments, including SaaS ↔ Self-Hosted, Self-Hosted ↔ Self-Hosted, and SaaS ↔ SaaS.
12-
[new-arch-migration](./new-arch-migration) | Assists in transitioning from the legacy GitGuardian architecture to the new architecture for Self-Hosted environments.
13-
[helm-preflights](./helm-preflights) | Ensures GitGuardian requirements are met prior installation or upgrade via [Helm on existing clusters](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm) by conducting tests from both the local user and the Kubernetes cluster.
14-
[honeytoken-tools](./honeytoken-tools) | Script to disseminate honeytokens in your repositories via Pull Requests
15-
[team-mapping-github-gitguardian](./team-mapping-github-gitguardian) | An example script using the GitHub and GitGuardian APIs to map GitHub Teams and the repositories they own to GitGuardian Teams and their perimeters.
9+
| Tools | Description |
10+
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
11+
| [api-migration](./api-migration) | Facilitates the migration of incident remediation progress across different environments, including SaaS ↔ Self-Hosted, Self-Hosted ↔ Self-Hosted, and SaaS ↔ SaaS. |
12+
| [new-arch-migration](./new-arch-migration) | Assists in transitioning from the legacy GitGuardian architecture to the new architecture for Self-Hosted environments. |
13+
| [helm-preflights](./helm-preflights) | Ensures GitGuardian requirements are met prior installation or upgrade via [Helm on existing clusters](https://docs.gitguardian.com/self-hosting/installation/installation-existing-helm) by conducting tests from both the local user and the Kubernetes cluster. |
14+
| [honeytoken-tools](./honeytoken-tools) | Script to disseminate honeytokens in your repositories via Pull Requests |
15+
| [team-mapping-github-gitguardian](./team-mapping-github-gitguardian) | An example script using the GitHub and GitGuardian APIs to map GitHub Teams and the repositories they own to GitGuardian Teams and their perimeters. |
16+
| [team-mapping-gitlab-gitguardian](./team-mapping-gitlab-gitguardian) | An example script using the Gitlab and GitGuardian APIs to map Gitlab Groups and the repositories they own to GitGuardian Teams and their perimeters. |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Changelog
2+
3+
## 2025-01-02
4+
5+
### Added
6+
7+
- Support user and user team synchronization.
8+
- Support project and team sources synchronization.
9+
- Rely on python Logging and support logging level in the configuration.
10+
- Use py-gitguardian for calls made to the GitGuardian API.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Team mapping: Gitlab to GitGuardian
2+
3+
The included scripts provide an example of using the Gitlab and GitGuardian
4+
APIs to map Gitlab groups and the repositories they own to GitGuardian Teams and
5+
their perimeters.
6+
7+
> [!CAUTION]
8+
> This is example code that can be used as a starting point for your own
9+
> solution. While we're happy to answer questions about it _it is not a
10+
> supported part of the product_.
11+
12+
### Installation
13+
14+
The easiest method of installation is to use Python virtual environment (venv):
15+
16+
```
17+
unzip team-mapping-gitlab-gitguardian.zip
18+
cd team-mapping-gitlab-gitguardian
19+
python3 -mvenv .venv
20+
source .venv/bin/activate
21+
pip install -r requirements.txt
22+
```
23+
24+
### Configuration
25+
26+
Three environment variables must be set to configure the connection:
27+
28+
- `GITLAB_URL` - The base URL for your Gitlab instance.
29+
- `GITLAB_ACCESS_TOKEN` - A Gitlab PAT with `read_api` and `read_user` permissions.
30+
- `GITGUARDIAN_API_KEY` - A GitGuardian API Service Account Token with `members:read`, `members:write`, `teams:read`, `teams:write`, `sources:read` and `sources:write` permissions.
31+
32+
> [!TIP]
33+
> If a Personal Access Token is used, the user who owns the PAT will be added
34+
> to all teams when they're created. SATs are preferred for this reason.
35+
36+
Optional environment variables:
37+
38+
- `GITGUARDIAN_INSTANCE` - The URL of a self-hosted GitGuardian instance. Just the scheme and hostname: https://gitguardian.example.com
39+
- `SEND_EMAIL` - Defines whether we should send an email to users when sending invitations
40+
- `REMOVE_MEMBERS` - Defines whether we should delete users from teams if they are not in any Gitlab group
41+
- `EXCLUDE_ADMIN` - Defines whether we should exclude admin users from sync
42+
- `DEFAULT_INCIDENT_PERMISSION` - Defines the default incident permission level for team members, defaults to `can_edit`, it's value must be one of :
43+
- `can_view` : For read permissions
44+
- `can_edit` : For read and write permissions
45+
- `full_access` : For manager permissions
46+
47+
In order to ensure you have the correct configuration, you can run the following command to display the configuration:
48+
49+
```
50+
python config.py
51+
```
52+
53+
### Nested groups
54+
55+
Teams in GitGuardian will be created based on the full path of the group of every user's group.
56+
57+
This means that if a user is in `top-group / middle-group / bottom-group`, he will be added to the team `top-group / middle-group / bottom-group` in GitGuardian.
58+
59+
### Invoking
60+
61+
Upon invocation, the script will sync teams and their perimeters from Gitlab to GitGuardian. It can be invoked like this:
62+
63+
```
64+
python sync_gitlab.py
65+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import logging
2+
import os
3+
4+
from pygitguardian.client import GGClient
5+
from functools import cached_property
6+
from dataclasses import dataclass
7+
8+
from pygitguardian.models import IncidentPermission
9+
10+
11+
@dataclass
12+
class Config:
13+
gitlab_token: str
14+
gitguardian_api_key: str
15+
gitguardian_url: str
16+
17+
gitlab_url: str
18+
19+
send_email: bool
20+
exclude_admin: bool
21+
default_incident_permission: IncidentPermission = IncidentPermission.EDIT
22+
logger_level: str = logging.INFO
23+
remove_members: bool = False
24+
pagination_size: int = 100
25+
26+
@classmethod
27+
def from_env(cls):
28+
incident_permission = cls.default_incident_permission
29+
if incident_permission_env := os.environ.get("DEFAULT_INCIDENT_PERMISSION"):
30+
incident_permission = IncidentPermission(incident_permission_env)
31+
32+
logger_level = logging._nameToLevel[
33+
os.environ.get("LOG_LEVEL", logging._levelToName[cls.logger_level])
34+
]
35+
36+
return cls(
37+
gitlab_token=os.environ["GITLAB_ACCESS_TOKEN"],
38+
gitguardian_api_key=os.environ["GITGUARDIAN_API_KEY"],
39+
gitlab_url=os.environ.get("GITLAB_URL", "https://gitlab.com"),
40+
gitguardian_url=os.environ.get(
41+
"GITGUARDIAN_INSTANCE", "https://api.gitguardian.com"
42+
),
43+
send_email=os.environ.get("SEND_EMAIL", "True") == "True",
44+
exclude_admin=os.environ.get("EXCLUDE_ADMIN", "True") == "True",
45+
default_incident_permission=incident_permission,
46+
logger_level=logger_level,
47+
)
48+
49+
@cached_property
50+
def client(self):
51+
return GGClient(api_key=self.gitguardian_api_key, base_uri=self.gitguardian_url)
52+
53+
def __repr__(self):
54+
return (
55+
"Config("
56+
f"send_email={self.send_email}, "
57+
f"gitlab_url={self.gitlab_url}, "
58+
f"gitlab_token={self.gitlab_token}, "
59+
f"logger_level={logging._levelToName[self.logger_level]}, "
60+
f"exclude_admin={self.exclude_admin}, "
61+
f"remove_members={self.remove_members}, "
62+
f"gitguardian_url={self.gitguardian_url}, "
63+
f"gitguardian_api_key={self.gitguardian_api_key}, "
64+
f"default_incident_permission={self.default_incident_permission}"
65+
")"
66+
)
67+
68+
69+
CONFIG = Config.from_env()
70+
71+
if __name__ == "__main__":
72+
print(CONFIG)

0 commit comments

Comments
 (0)