Commit 1d1da4dd authored by nono's avatar nono 💻
Browse files

Initial commit, based on Mindiel's code.

parents
# Otto : Gitlab Spam Kill
> Développé par Mindiel pour La Quadrature du Net
## Usage
Avant toute chose, remplissez les variables `GITLAB_URL` et `PRIVATE_TOKEN` dans le fichier `gitlab.py`. [Voir la documentation pour obtenir un token.](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html)
Tout d'abord, nous allons lancer le script permettant de lister nouveaux utilisateurices des 30 derniers jours avec ;
`python otto.py last users 30`
Une fois le spam identifié avec nos beaux yeaux, nous pouvons lancer la suppression des utilisateurices avec la commande suivante ;
`python otto.py delete users 456-457`
Pour supprimer les utilisateurs dont l'id est situé entre 456 et 457
Il existe une whitelist, dans le fichier `whitelist.json`, qui permet d'éviter la suppression des utiliateurices, malgré leur présence dans l'interval précédent.
> A utiliser avec l'amie "Parcimonie" donc ;o)
#encoding: utf-8
"""
Ensemble d'utilitaires pour gitlab, via son API.
"""
import requests
GITLAB_URL = "https://gitlab.example.net/api/v4/"
PRIVATE_TOKEN = ""
# Création d'une nouvelle Session
session = requests.Session()
session.headers.update({
"PRIVATE-TOKEN": PRIVATE_TOKEN,
})
parameters = {
"per_page": 100,
"page": 1,
}
def list_items(object_name, page=1):
parameters["page"] = page
response = session.get(GITLAB_URL + object_name, params=parameters)
if response.encoding is None:
response.encoding = "ISO-8859-1"
if response.status_code==200:
return response.json()
return []
def list_objects(object_name):
objects = []
page = 1
temp_objects = list_items(object_name, page)
while temp_objects!=[]:
objects.extend(temp_objects)
page += 1
temp_objects = list_items(object_name, page)
return objects
def list_groups():
return list_objects("groups")
def list_projects():
return list_objects("projects")
def list_users():
return list_objects("users")
def user_detail(user_id):
response = session.get(GITLAB_URL + "users/%d" % user_id)
if response.encoding is None:
response.encoding = "ISO-8859-1"
if response.status_code==200:
return response.json()
return []
def delete_user(user_id):
data = {
"hard_delete": True,
}
response = session.delete(GITLAB_URL + "users/%d" % user_id, data=data)
#encoding: utf-8
"""
Otto liste les groupes, les projets, et les utilisateurs d'un site gitlab
afin de permettre à des humains de signaler du spam simplement.
options :
- list groups : Liste les groupes inconnus
- add group name : Ajoute le groupe "name" aux groupes connus
"""
from datetime import datetime, timedelta
import json
import sys
import time
from gitlab import list_groups, list_projects, list_users, delete_user, user_detail
if __name__=="__main__":
if len(sys.argv)<3:
print("usage")
exit()
elif len(sys.argv)==3:
if sys.argv[1]=="search":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2]=="groups":
# On parcourt l'ensemble des groupes afin de signaler les inconnus
for group in list_groups():
if group["name"] not in whitelists["groups"]:
print(group["name"])
elif sys.argv[2]=="projects":
# On parcourt l'ensemble des projets afin de signaler les inconnus
for project in list_projects():
if project["name"] not in whitelists["projects"] and project["namespace"]["name"] not in whitelists["namespaces"]:
print("%s (%s)" % (project["name"], project["namespace"]["name"]))
elif sys.argv[2]=="users":
# On parcourt l'ensemble des utilisateurs afin de signaler les inconnus
for user in list_users():
if user["name"] not in whitelists["users"] and user["name"] not in whitelists["namespaces"]:
found = False
for domain in whitelists["domains"]:
if user["email"].endswith(domain):
found = True
break
if not found:
print("%5d: %s - %s" % (user["id"], user["name"], user["email"]))
else:
print("unknown option %s" % sys.argv[2])
elif sys.argv[1]=="list":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2] in ("groups", "projects", "users", "namespaces", "domains"):
for item in whitelists[sys.argv[2]]:
print(item)
else:
print("unknown option %s" % sys.argv[2])
elif sys.argv[1]=="clear":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2] in ("groups", "projects", "users", "namespaces", "domains"):
whitelists[sys.argv[2]].clear()
with open("whitelists.json", "w") as f:
json.dump(whitelists, f, indent=4)
else:
print("unknown option %s" % sys.argv[2])
elif len(sys.argv)==4:
if sys.argv[1]=="add":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2] in ("group", "project", "user", "namespace", "domain"):
whitelists["%ss" % sys.argv[2]].append(sys.argv[3])
with open("whitelists.json", "w") as f:
json.dump(whitelists, f, indent=4)
else:
print("unknown option %s" % sys.argv[2])
elif sys.argv[1]=="remove":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2] in ("group", "project", "user", "namespace", "domain"):
whitelists["%ss" % sys.argv[2]].remove(sys.argv[3])
with open("whitelists.json", "w") as f:
json.dump(whitelists, f, indent=4)
else:
print("unknown option %s" % sys.argv[2])
elif sys.argv[1]=="last":
# Chargement des listes blanches
with open("whitelists.json") as f:
whitelists = json.loads(f.read())
if sys.argv[2]=="groups":
# On parcourt l'ensemble des groupes afin de signaler les inconnus
for group in list_groups():
if group["name"] not in whitelists["groups"]:
print(group["name"])
elif sys.argv[2]=="projects":
# On parcourt l'ensemble des projets afin de signaler les inconnus
for project in list_projects():
if project["name"] not in whitelists["projects"] and project["namespace"]["name"] not in whitelists["namespaces"]:
print("%s (%s)" % (project["name"], project["namespace"]["name"]))
elif sys.argv[2]=="users":
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# On parcourt l'ensemble des utilisateurs afin de signaler les inconnus
for user in list_users():
if datetime.strptime(user["created_at"][:19], "%Y-%m-%dT%H:%M:%S")>(datetime.now()-timedelta(days=int(sys.argv[3]))):
if user["name"] not in whitelists["users"] and user["name"] not in whitelists["namespaces"]:
found = False
for domain in whitelists["domains"]:
if user["email"].endswith(domain):
found = True
break
if not found:
print("%5d: %s - %s" % (user["id"], user["name"], user["email"]))
#print(json.dumps(user, indent=4))
#print(json.dumps(user_detail(user["id"]), indent=4))
else:
print("unknown option %s" % sys.argv[2])
elif sys.argv[1]=="delete":
if sys.argv[2]=="users":
# On supprime l'ensemble des utilisateurs dont les ids sont compris entre début et fin
debut = int(sys.argv[3].split("-")[0])
fin = int(sys.argv[3].split("-")[1])
for user_id in range(debut, fin+1):
delete_user(user_id)
else:
print("unknown option %s" % sys.argv[2])
else:
print("unknown command %s" % sys.argv[1])
{
"groups": [
"GAFAM",
"Site",
"Respect my Net",
"LQdN interne",
"La Quadrature du Net",
"Political Memory",
"grange",
"rpteam",
"piphone"
],
"projects": [
"soutien",
"memopol",
"controle-tes-donnees.net",
"political_memory",
"Respect My Net",
"wantzel",
"don"
],
"domains": [
"laquadrature.net"
],
"users": [
"Gibus",
"Ugo",
"Ag3m",
"Genma",
"Bram",
"datapulte",
"Herdir",
"taziden",
"quota_atypique",
"rpadawan"
],
"namespaces": [
"Site",
"LQdN interne",
"La Quadrature du Net",
"okhin",
"piphone",
"Porkepix",
"mmu_man",
"Political Memory",
"Oncela5eva",
"Piks3l",
"vincib",
"GAFAM",
"grange",
"luxcem",
"Oncela",
"Respect my Net",
"Erneraude",
"jaster",
"nico",
"rpteam"
]
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment