gitlabrat 1.1__tar.gz → 1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitlabrat-1.1 → gitlabrat-1.3}/.gitignore +1 -1
- gitlabrat-1.3/PKG-INFO +59 -0
- gitlabrat-1.3/README.md +34 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/agents.py +1 -1
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/auth.py +3 -2
- gitlabrat-1.3/labrat/cli/groups.py +55 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/controllers/agents.py +1 -1
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/controllers/auth.py +8 -4
- gitlabrat-1.3/labrat/controllers/groups.py +81 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/core/agent.py +0 -3
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/main.py +2 -2
- {gitlabrat-1.1 → gitlabrat-1.3}/pyproject.toml +5 -5
- gitlabrat-1.1/PKG-INFO +0 -72
- gitlabrat-1.1/README.md +0 -47
- {gitlabrat-1.1 → gitlabrat-1.3}/LICENSE +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/__init__.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/__init__.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/common.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/projects.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/cli/users.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/controllers/__init__.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/controllers/projects.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/controllers/users.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/core/__init__.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/core/config.py +0 -0
- {gitlabrat-1.1 → gitlabrat-1.3}/labrat/core/utils.py +0 -0
|
@@ -183,7 +183,7 @@ cython_debug/
|
|
|
183
183
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
184
184
|
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
185
185
|
# you could uncomment the following to ignore the entire vscode folder
|
|
186
|
-
|
|
186
|
+
.vscode/
|
|
187
187
|
|
|
188
188
|
# Ruff stuff:
|
|
189
189
|
.ruff_cache/
|
gitlabrat-1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitlabrat
|
|
3
|
+
Version: 1.3
|
|
4
|
+
Summary: LabRat: GitLab exploitation orchestrator
|
|
5
|
+
Project-URL: Homepage, https://github.com/JChamblee99/Labrat
|
|
6
|
+
Project-URL: Repository, https://github.com/JChamblee99/Labrat.git
|
|
7
|
+
Project-URL: Issues, https://github.com/JChamblee99/Labrt/issues
|
|
8
|
+
Author-email: John Chamblee <conway.py@proton.farm>
|
|
9
|
+
License: GPL-3.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Requires-Dist: beautifulsoup4>=4.9.0
|
|
21
|
+
Requires-Dist: gitpython>=3.1.0
|
|
22
|
+
Requires-Dist: python-gitlab>=3.0.0
|
|
23
|
+
Requires-Dist: requests>=2.25.0
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
<div align="center">
|
|
27
|
+
|
|
28
|
+
# Labrat
|
|
29
|
+
|
|
30
|
+
**Living rent-free in the walls of your GitLab.**
|
|
31
|
+
|
|
32
|
+
[](https://pypi.org/project/gitlabrat/)
|
|
33
|
+
[](https://pypi.org/project/gitlabrat/)
|
|
34
|
+
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
35
|
+
[](https://github.com/JChamblee99/LabRat/commits/main)
|
|
36
|
+
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Overview
|
|
42
|
+
|
|
43
|
+
Labrat automates workflows for gaining and maintaining access to GitLab instances and CI/CD pipelines.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install gitlabrat
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Authenticate to a GitLab instance
|
|
55
|
+
labrat auth -t https://gitlab.example.com -u username -p password
|
|
56
|
+
|
|
57
|
+
# List authenticated agents
|
|
58
|
+
labrat agents ls
|
|
59
|
+
```
|
gitlabrat-1.3/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Labrat
|
|
4
|
+
|
|
5
|
+
**Living rent-free in the walls of your GitLab.**
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/gitlabrat/)
|
|
8
|
+
[](https://pypi.org/project/gitlabrat/)
|
|
9
|
+
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
10
|
+
[](https://github.com/JChamblee99/LabRat/commits/main)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
Labrat automates workflows for gaining and maintaining access to GitLab instances and CI/CD pipelines.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install gitlabrat
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Authenticate to a GitLab instance
|
|
30
|
+
labrat auth -t https://gitlab.example.com -u username -p password
|
|
31
|
+
|
|
32
|
+
# List authenticated agents
|
|
33
|
+
labrat agents ls
|
|
34
|
+
```
|
|
@@ -21,7 +21,7 @@ def build_parser(parsers):
|
|
|
21
21
|
|
|
22
22
|
def handle_list_args(args):
|
|
23
23
|
# Prepare table
|
|
24
|
-
headers = ["Host", "ID", "Username", "Name", "Authenticated", "Is Admin", "Is Bot", "Password", "Private Token"]
|
|
24
|
+
headers = ["Host", "ID", "Username", "Name", "Is Authenticated", "Is Admin", "Is Bot", "Password", "Private Token"]
|
|
25
25
|
data = []
|
|
26
26
|
|
|
27
27
|
for agent in args.controller.list(args.filter):
|
|
@@ -13,6 +13,7 @@ def build_parser(parsers):
|
|
|
13
13
|
parser.add_argument("-r", "--re-auth", action="store_true", help="Re-authenticate with stored credentials")
|
|
14
14
|
parser.add_argument("-n", "--token-name", required=False, help="Name for the access token", default="private token")
|
|
15
15
|
parser.add_argument("-s", "--scopes", required=False, help="Comma-separated list of scopes for the access token", default="api,read_repository,write_repository")
|
|
16
|
+
parser.add_argument("-a", "--access-token", required=False, help="Access token for authentication")
|
|
16
17
|
|
|
17
18
|
parser.set_defaults(func=handle_args, _parser=parser)
|
|
18
19
|
parser.set_defaults(controller=Auth())
|
|
@@ -20,7 +21,7 @@ def build_parser(parsers):
|
|
|
20
21
|
|
|
21
22
|
def handle_args(args):
|
|
22
23
|
has_targets = args.target or args.target_file
|
|
23
|
-
has_credentials = (args.username and args.password) or args.combo_list
|
|
24
|
+
has_credentials = (args.username and args.password) or args.combo_list or args.access_token
|
|
24
25
|
can_auth = has_targets and has_credentials
|
|
25
26
|
|
|
26
27
|
if args.re_auth or can_auth:
|
|
@@ -53,7 +54,7 @@ def auth(args):
|
|
|
53
54
|
scopes = args.scopes.split(",") if args.scopes else []
|
|
54
55
|
|
|
55
56
|
# Iterate over each user and target
|
|
56
|
-
for agent, err in args.controller.reauth(token_name=args.token_name, token_scopes=scopes, targets=targets, users=[user[0] for user in users]) if args.re_auth else args.controller.auth(targets, users, token_name=args.token_name, token_scopes=scopes, use_ldap=args.use_ldap):
|
|
57
|
+
for agent, err in args.controller.reauth(token_name=args.token_name, token_scopes=scopes, targets=targets, users=[user[0] for user in users]) if args.re_auth else args.controller.auth(targets, users, token_name=args.token_name, token_scopes=scopes, private_token=args.access_token, use_ldap=args.use_ldap):
|
|
57
58
|
if err:
|
|
58
59
|
print(f"[-] Authentication failed for {agent.label}: {err}")
|
|
59
60
|
else:
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
import gitlab
|
|
4
|
+
|
|
5
|
+
from labrat.cli import common
|
|
6
|
+
from labrat.controllers.groups import Groups
|
|
7
|
+
|
|
8
|
+
def build_parser(parsers):
|
|
9
|
+
parser = parsers.add_parser("groups", help="Manage GitLab groups")
|
|
10
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
11
|
+
|
|
12
|
+
list_parser = common.add_filtered_parser(subparsers, "list", handle_list_args, aliases=["ls"], help="List GitLab groups", filter_required=False)
|
|
13
|
+
list_parser.add_argument("-m", "--min-access-level", required=False, type=int, help="Minimum access level to filter groups", default=0)
|
|
14
|
+
list_parser.add_argument("-u", "--user", action="append", required=False, help="Filter agent performing action")
|
|
15
|
+
|
|
16
|
+
create_token_parser = common.add_filtered_parser(subparsers, "create_token", handle_create_token_args, help="Create an access token", filter_required=True)
|
|
17
|
+
create_token_parser.add_argument("-l", "--access-level", required=False, type=int, help="Access level for the access token", default=50)
|
|
18
|
+
create_token_parser.add_argument("-d", "--days", required=False, type=int, help="Number of days until the token expires", default=60)
|
|
19
|
+
create_token_parser.add_argument("-n", "--token-name", required=False, help="Name for the access token", default="project_bot")
|
|
20
|
+
create_token_parser.add_argument("-s", "--scopes", required=False, help="Comma-separated list of scopes for the access token", default="api,read_repository,write_repository")
|
|
21
|
+
create_token_parser.add_argument("-u", "--user", action="append", required=False, help="Filter agent performing action")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
parser.set_defaults(controller=Groups())
|
|
25
|
+
return subparsers
|
|
26
|
+
|
|
27
|
+
def handle_list_args(args):
|
|
28
|
+
headers = ["Host", "ID", "Name", "Access Level", "Agents"]
|
|
29
|
+
data = []
|
|
30
|
+
|
|
31
|
+
for group in args.controller.list(args.filter, args.user):
|
|
32
|
+
# color each username by that agent's access level (higher -> brighter)
|
|
33
|
+
usernames = []
|
|
34
|
+
for agent in group.agents:
|
|
35
|
+
colored_username = common.color_access_level(agent.access_level, f"{agent.username} ({agent.access_level})")
|
|
36
|
+
usernames.append(colored_username)
|
|
37
|
+
|
|
38
|
+
# Add group information to data table
|
|
39
|
+
data.append([
|
|
40
|
+
group.host,
|
|
41
|
+
group.id,
|
|
42
|
+
group.name,
|
|
43
|
+
f"{group.access_level} ({gitlab.const.AccessLevel(group.access_level).name.lower()})",
|
|
44
|
+
", ".join(usernames)
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
common.print_table(headers, data)
|
|
48
|
+
|
|
49
|
+
def handle_create_token_args(args):
|
|
50
|
+
expiration = (datetime.datetime.now() + datetime.timedelta(days=args.days)).strftime("%Y-%m-%d")
|
|
51
|
+
for group, agent, err in args.controller.create_token(args.token_name, args.access_level, args.scopes.split(","), expiration, args.user, args.filter):
|
|
52
|
+
if err:
|
|
53
|
+
print(f"[!] Failed to create access token for {group.web_url}: {err}")
|
|
54
|
+
else:
|
|
55
|
+
print(f"[+] Successfully created access token for {group.web_url}: {agent.private_token}")
|
|
@@ -6,7 +6,7 @@ class Auth:
|
|
|
6
6
|
def __init__(self):
|
|
7
7
|
self.config = Config()
|
|
8
8
|
|
|
9
|
-
def auth(self, targets, users, token_name, token_scopes, use_ldap=False):
|
|
9
|
+
def auth(self, targets, users, token_name, token_scopes, private_token, use_ldap=False):
|
|
10
10
|
"""Authenticate and create a PAT for each user on each target.
|
|
11
11
|
|
|
12
12
|
Keyword arguments:
|
|
@@ -19,10 +19,14 @@ class Auth:
|
|
|
19
19
|
|
|
20
20
|
for username, password in users:
|
|
21
21
|
for target in targets:
|
|
22
|
-
agent = Agent(target, use_ldap, username, password)
|
|
23
22
|
try:
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
if private_token:
|
|
24
|
+
agent = Agent(url=target, username=username, private_token=private_token)
|
|
25
|
+
else:
|
|
26
|
+
agent = Agent(url=target, username=username, password=password, use_ldap=use_ldap)
|
|
27
|
+
agent.login()
|
|
28
|
+
agent.auth(private_token=agent.create_pat(token_name, token_scopes))
|
|
29
|
+
|
|
26
30
|
self.config[agent.section] = agent.to_dict()
|
|
27
31
|
yield agent, None
|
|
28
32
|
except Exception as e:
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
from labrat.core.agent import Agent
|
|
4
|
+
from labrat.core.config import Config
|
|
5
|
+
from labrat.core.utils import obj_filter
|
|
6
|
+
|
|
7
|
+
class Groups:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.config = Config(authed_only=True)
|
|
10
|
+
|
|
11
|
+
def list(self, filter=None, agent_filter=None, min_level=0):
|
|
12
|
+
"""List groups accessible by agents.
|
|
13
|
+
|
|
14
|
+
Keyword arguments:
|
|
15
|
+
- filter: Regex filter and field selection passed to `utils.obj_filter()` for group objects
|
|
16
|
+
- agent_filter: Regex filter and field selection passed to `utils.obj_filter()` for agent objects
|
|
17
|
+
- min_level: Minimum desired access level for agent to return a group
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
group_map = {}
|
|
21
|
+
for section, agent in self.config.filter(agent_filter):
|
|
22
|
+
groups = agent.gitlab.groups.list(all=True)
|
|
23
|
+
for group in groups:
|
|
24
|
+
access_level = self.get_group_access_level(agent, group)
|
|
25
|
+
if access_level < min_level:
|
|
26
|
+
continue
|
|
27
|
+
|
|
28
|
+
# Agent enrichment with shallow copy
|
|
29
|
+
agent_copy = copy.copy(agent)
|
|
30
|
+
agent_copy.access_level = access_level
|
|
31
|
+
|
|
32
|
+
# Group enrichment
|
|
33
|
+
group.host = agent.host
|
|
34
|
+
|
|
35
|
+
# Add group and agent to map
|
|
36
|
+
if group.web_url not in group_map:
|
|
37
|
+
group.agents = [agent_copy]
|
|
38
|
+
group.access_level = access_level
|
|
39
|
+
group_map[group.web_url] = group
|
|
40
|
+
else:
|
|
41
|
+
group_map[group.web_url].agents.append(agent_copy)
|
|
42
|
+
group_map[group.web_url].access_level = max(group_map[group.web_url].access_level, access_level)
|
|
43
|
+
|
|
44
|
+
return [group for group in group_map.values() if not filter or obj_filter(group, filter)]
|
|
45
|
+
|
|
46
|
+
def create_token(self, name, access_level, scopes, expires_at, agent_filter=None, filter=None):
|
|
47
|
+
""" Create Group Access Tokens.
|
|
48
|
+
|
|
49
|
+
Keyword arguments:
|
|
50
|
+
- name: Name of the access token.
|
|
51
|
+
- access_level: Access level of the created PAT.
|
|
52
|
+
- scopes: List of scopes for the created PAT. (e.g. `['read_repository', 'write_repository']`)
|
|
53
|
+
- expires_at: ISO format expiration date for the created PAT.
|
|
54
|
+
- agent_filter: Regex filter and field selection passed to `utils.obj_filter()` for agent objects.
|
|
55
|
+
- filter: Regex filter and field selection passed to `utils.obj_filter()` for group objects.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
for group in self.list(filter=filter, agent_filter=agent_filter, min_level=50):
|
|
59
|
+
agent = group.agents[0]
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
req = group.access_tokens.create({
|
|
63
|
+
'name': name,
|
|
64
|
+
'access_level': access_level,
|
|
65
|
+
'scopes': scopes,
|
|
66
|
+
'expires_at': expires_at
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
section = f"{req.user_id}_{group.id}@{agent.host}"
|
|
70
|
+
group_agent = Agent(agent.url, username=name, private_token=req.token, section=section)
|
|
71
|
+
self.config[section] = group_agent.to_dict()
|
|
72
|
+
|
|
73
|
+
yield group, group_agent, None
|
|
74
|
+
except Exception as e:
|
|
75
|
+
yield group, None, e
|
|
76
|
+
|
|
77
|
+
def get_group_access_level(self, agent, group):
|
|
78
|
+
try:
|
|
79
|
+
return group.members.get(agent.id).access_level
|
|
80
|
+
except Exception as e:
|
|
81
|
+
return 60 if agent.is_admin else 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# labrat/main.py
|
|
2
2
|
import argparse
|
|
3
|
-
from labrat.cli import agents, auth, projects, users
|
|
3
|
+
from labrat.cli import agents, auth, projects, groups, users
|
|
4
4
|
|
|
5
5
|
def main():
|
|
6
6
|
parser = argparse.ArgumentParser(
|
|
@@ -9,7 +9,7 @@ def main():
|
|
|
9
9
|
)
|
|
10
10
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
11
11
|
|
|
12
|
-
for command in [agents, auth, projects, users]:
|
|
12
|
+
for command in [agents, auth, projects, groups, users]:
|
|
13
13
|
command.build_parser(subparsers)
|
|
14
14
|
|
|
15
15
|
args = parser.parse_args()
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitlabrat"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3"
|
|
8
8
|
description = "LabRat: GitLab exploitation orchestrator"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -13,7 +13,7 @@ authors = [
|
|
|
13
13
|
]
|
|
14
14
|
license = {text = "GPL-3.0"}
|
|
15
15
|
classifiers = [
|
|
16
|
-
"Development Status ::
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
17
|
"Intended Audience :: Developers",
|
|
18
18
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
19
19
|
"Programming Language :: Python :: 3",
|
|
@@ -30,9 +30,9 @@ dependencies = [
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
|
-
Homepage = "https://github.com/JChamblee99/
|
|
34
|
-
Repository = "https://github.com/JChamblee99/
|
|
35
|
-
Issues = "https://github.com/JChamblee99/
|
|
33
|
+
Homepage = "https://github.com/JChamblee99/Labrat"
|
|
34
|
+
Repository = "https://github.com/JChamblee99/Labrat.git"
|
|
35
|
+
Issues = "https://github.com/JChamblee99/Labrt/issues"
|
|
36
36
|
|
|
37
37
|
[project.scripts]
|
|
38
38
|
labrat = "labrat.main:main"
|
gitlabrat-1.1/PKG-INFO
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: gitlabrat
|
|
3
|
-
Version: 1.1
|
|
4
|
-
Summary: LabRat: GitLab exploitation orchestrator
|
|
5
|
-
Project-URL: Homepage, https://github.com/JChamblee99/LabRat
|
|
6
|
-
Project-URL: Repository, https://github.com/JChamblee99/LabRat.git
|
|
7
|
-
Project-URL: Issues, https://github.com/JChamblee99/LabRat/issues
|
|
8
|
-
Author-email: John Chamblee <conway.py@proton.farm>
|
|
9
|
-
License: GPL-3.0
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Requires-Python: >=3.8
|
|
20
|
-
Requires-Dist: beautifulsoup4>=4.9.0
|
|
21
|
-
Requires-Dist: gitpython>=3.1.0
|
|
22
|
-
Requires-Dist: python-gitlab>=3.0.0
|
|
23
|
-
Requires-Dist: requests>=2.25.0
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
|
|
26
|
-
# LabRat
|
|
27
|
-
|
|
28
|
-
LabRat is a GitLab exploitation orchestrator designed for security researchers and penetration testers.
|
|
29
|
-
|
|
30
|
-
## Features
|
|
31
|
-
|
|
32
|
-
- **Authentication Management** - Authenticate to GitLab servers and manage access tokens
|
|
33
|
-
- **Project Management** - List, clone, and manipulate GitLab projects
|
|
34
|
-
- **User Management** - Enumerate and create access tokens for GitLab users
|
|
35
|
-
- **Agent Management** - Manage multiple GitLab agents and credentials
|
|
36
|
-
|
|
37
|
-
## Installation
|
|
38
|
-
|
|
39
|
-
Install LabRat from PyPI:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
pip install gitlabrat
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Usage
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
labrat --help
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Commands
|
|
52
|
-
|
|
53
|
-
- `labrat auth` - Authenticate to GitLab server(s)
|
|
54
|
-
- `labrat agents` - Manage GitLab agents
|
|
55
|
-
- `labrat projects` - Manage GitLab projects
|
|
56
|
-
- `labrat users` - Manage GitLab users
|
|
57
|
-
|
|
58
|
-
## Requirements
|
|
59
|
-
|
|
60
|
-
- Python 3.8+
|
|
61
|
-
- python-gitlab
|
|
62
|
-
- GitPython
|
|
63
|
-
- beautifulsoup4
|
|
64
|
-
- requests
|
|
65
|
-
|
|
66
|
-
## License
|
|
67
|
-
|
|
68
|
-
GNU General Public License v3.0 (GPL-3.0)
|
|
69
|
-
|
|
70
|
-
## Author
|
|
71
|
-
|
|
72
|
-
John Chamblee
|
gitlabrat-1.1/README.md
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# LabRat
|
|
2
|
-
|
|
3
|
-
LabRat is a GitLab exploitation orchestrator designed for security researchers and penetration testers.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Authentication Management** - Authenticate to GitLab servers and manage access tokens
|
|
8
|
-
- **Project Management** - List, clone, and manipulate GitLab projects
|
|
9
|
-
- **User Management** - Enumerate and create access tokens for GitLab users
|
|
10
|
-
- **Agent Management** - Manage multiple GitLab agents and credentials
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
Install LabRat from PyPI:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
pip install gitlabrat
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
labrat --help
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Commands
|
|
27
|
-
|
|
28
|
-
- `labrat auth` - Authenticate to GitLab server(s)
|
|
29
|
-
- `labrat agents` - Manage GitLab agents
|
|
30
|
-
- `labrat projects` - Manage GitLab projects
|
|
31
|
-
- `labrat users` - Manage GitLab users
|
|
32
|
-
|
|
33
|
-
## Requirements
|
|
34
|
-
|
|
35
|
-
- Python 3.8+
|
|
36
|
-
- python-gitlab
|
|
37
|
-
- GitPython
|
|
38
|
-
- beautifulsoup4
|
|
39
|
-
- requests
|
|
40
|
-
|
|
41
|
-
## License
|
|
42
|
-
|
|
43
|
-
GNU General Public License v3.0 (GPL-3.0)
|
|
44
|
-
|
|
45
|
-
## Author
|
|
46
|
-
|
|
47
|
-
John Chamblee
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|