You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Architecture.md
+254Lines changed: 254 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -55,3 +55,257 @@ Three types of policies can be applied to incoming pushes:
55
55
- For example, `checkCommitMessages` which reads the configuration and matches the string patterns provided with the commit messages in the push in order to block it.
56
56
- Custom policies (Plugins): Writing your own Push/Pull plugins provides more flexibility for implementing an organization's rules. For more information, see the guide on writing plugins.
57
57
<!-- Todo: add link to plugin guide -->
58
+
59
+
## The nitty gritty
60
+
61
+
### Action Chains
62
+
63
+
Action chains are a list of processors that a Git operation automatically goes through before awaiting approval. Three action chains are currently available:
64
+
65
+
#### Push action chain
66
+
67
+
<!-- Todo: Link all the action chains below -->
68
+
69
+
Executed when a user makes a `git push` to GitProxy. These are the actions in `pushActionChain`, by order of execution:
70
+
71
+
-`parsePush`
72
+
-`checkEmptyBranch`
73
+
-`checkRepoInAuthorisedList`
74
+
-`checkCommitMessages`
75
+
-`checkAuthorEmails`
76
+
-`checkUserPushPermission`
77
+
-`pullRemote`
78
+
-`writePack`
79
+
-`checkHiddenCommits`
80
+
-`checkIfWaitingAuth`
81
+
-`preReceive`
82
+
-`getDiff`
83
+
-`gitleaks`
84
+
-`clearBareClone`
85
+
-`scanDiff`
86
+
-`blockForAuth`
87
+
88
+
#### Pull action chain
89
+
90
+
Executed when a user makes a `git clone` or `git pull` to GitProxy:
91
+
92
+
-`checkRepoInAuthorisedList`
93
+
94
+
#### Default action chain
95
+
96
+
This chain is executed when making any operation other than a `git push` or `git pull`.
97
+
98
+
-`checkRepoInAuthorisedList`
99
+
<!-- Todo: add example and verify this from original PR -->
100
+
101
+
### Processors
102
+
103
+
Processors (also known as: push/pull actions) represent operations that each push or pull must go through in order to get approved or rejected.
104
+
105
+
Processors do not necessarily represent policies. Some processors are just operations that help fetch or process data: For example, `pullRemote` simply clones the remote repository from the Git host.
106
+
107
+
#### `checkRepoInAuthorisedList`
108
+
109
+
Checks if the URL of the repo being pushed to is present in the GitProxy repo database. If no repo URL in the database matches, the push is blocked.
Parses the push request data which comes from the Git client as a buffer that contains packet line data. If anything unexpected happens during parsing, such as malformed pack data or multiple ref updates in a single push, the push will get rejected.
116
+
117
+
Also handles extraction of push contents, such as commit and committer data.
Checks if the push contains any commit data, or is just an empty branch push (pushing a new branch without any additional commits). Empty branch pushes are blocked because subsequent processors require commit data to work correctly.
A **configurable** processor that blocks pushes containing commit messages that match the provided literals or patterns. These patterns can be configured in `proxy.config.json` or the active configuration file:
130
+
131
+
```json
132
+
"commitConfig": {
133
+
"author": {
134
+
"email": {
135
+
"local": {
136
+
"block": ""
137
+
},
138
+
"domain": {
139
+
"allow": ".*"
140
+
}
141
+
}
142
+
},
143
+
// Defines patterns/literals to block pushes based on their commit messages
144
+
"message": {
145
+
"block": {
146
+
"literals": [],
147
+
"patterns": []
148
+
}
149
+
},
150
+
"diff": {
151
+
"block": {
152
+
"literals": [],
153
+
"patterns": [],
154
+
"providers": {}
155
+
}
156
+
}
157
+
},
158
+
```
159
+
160
+
If the arrays are empty, the checks will pass and chain execution will continue.
161
+
162
+
Note that invalid regex patterns will also fail the `isMessageAllowed` check.
163
+
164
+
<!-- Todo: verify if this is the case and make an issue to improve error handling for this specifically. Also, the getCommitConfig is being called over and over for each commit message and can be optimized to fetch only once -->
Similar to `checkCommitMessages`, allows configuring allowed domains or blocked "locals" (the part before "@domain.com"). If any commit(s) author email(s) match the `local.block` regex, the push gets blocked. Likewise, if any of the emails' domains does not match the `domain.allow` regex, the push gets blocked.
171
+
172
+
If neither of these are configured (set to empty strings), then the checks will pass and chain execution will continue.
173
+
174
+
<!-- Todo: Check error handling for invalid regex -->
Clones the repository and temporarily stores it locally. For private repos, it obtains the authorization headers and uses them to authenticate the `git clone` operation.
193
+
194
+
For security reasons, the cloned repository is deleted later in `clearBareClone`.
Executes `git receive-pack` with the incoming pack data from the request body in order to receive the pushed data. It also identifies new `.idx` files in `.git/objects/pack` for other processors (such as `checkHiddenCommits`) to scan more efficiently.
201
+
202
+
Note that `writePack` sets Git's `receive.unpackLimit` to `0`, which forces Git to always create pack files instead of unpacking objects individually.
Checks if the action has been authorised (approved by a reviewer). If so, allows the push to continue to the remote. It simply continues chain execution if the push hasn't been approved.
Allows executing pre-receive hooks from `.sh` scripts located in the `./hooks` directory. **Also allows bypassing the manual approval process.** This enables admins to reuse GitHub enterprise commit policies and provide a seamless experience for contributors who no longer need to wait for approval or be aware of GitProxy intercepting their pushes.
223
+
224
+
Pre-receive hooks are a feature that allows blocking unwanted commits based on rules described in `.sh` scripts. GitHub provides a set of [sample rules](https://github.com/github/platform-samples/blob/master/pre-receive-hooks) to get started.
225
+
226
+
This processor will block the push depending on the exit status of the pre-receive hook:
227
+
228
+
- Exit status `0`: Sets the push to `autoApproved`, skipping the requirement for subsequent approval. Note that this doesn't affect the other processors, which may still block the push.
229
+
<!-- Todo: confirm whether pushes that passed the prereceive can still be blocked -->
230
+
- Exit status `1`: Sets the push to `autoRejected`, automatically rejecting the push regardless of whether the other processors succeed.
231
+
- Exit status `2`: Requires subsequent approval as any regular push.
Executes `git diff` to obtain the diff for the given revision range. If the commit data is empty or has no entries (possible due to a malformed push), the push is blocked.
238
+
239
+
The data extracted in this step is later used in `scanDiff`.
Runs [Gitleaks](https://github.com/gitleaks/gitleaks) to detect sensitive information such as API keys and passwords in the commits being pushed to prevent credentials from leaking.
246
+
247
+
The following parameters can be configured:
248
+
249
+
-`enabled`: Whether scanning is active. `false` by default
250
+
-`ignoreGitleaksAllow`: Forces scanning even if developers added `gitleaks:allow` comments
251
+
-`noColor`: Controls color output formatting
252
+
-`configPath`: Sets a custom Gitleaks rules file
253
+
254
+
This processor runs the Gitleaks check starting from the root commit to the `commitFrom` value present in the push. If the Gitleaks check fails (nonzero exit code), or otherwise cannot spawn, the push will be blocked.
Recursively removes the contents of `./.remote`, which is the location where the bare repository is cloned in `pullRemote`. This exists to prevent tampering with Git data.
261
+
262
+
<!-- Todo: improve the explanation of why clearBareClone is needed -->
A **configurable** processor that blocks pushes containing diff (changes) that match the provided literals or patterns. These patterns can be configured in `proxy.config.json` or the active configuration file:
269
+
270
+
```json
271
+
"commitConfig": {
272
+
"author": {
273
+
"email": {
274
+
"local": {
275
+
"block": ""
276
+
},
277
+
"domain": {
278
+
"allow": ".*"
279
+
}
280
+
}
281
+
},
282
+
"message": {
283
+
"block": {
284
+
"literals": [],
285
+
"patterns": []
286
+
}
287
+
},
288
+
// Defines patterns/literals to block pushes based on their diff
289
+
"diff": {
290
+
"block": {
291
+
"literals": [],
292
+
"patterns": [],
293
+
"providers": {}
294
+
}
295
+
}
296
+
},
297
+
```
298
+
299
+
This will scan every file changed and try to match the configured literals, patterns or providers. If any diff violations are found, the push is blocked.
This action appends a message to be displayed after all the processors have finished on a pre-approval push.
306
+
307
+
Note that this message will show again even if the push had been previously rejected by a reviewer. After a manual rejection, pushing again creates a new `action` object so that the push can be re-reviewed and approved.
0 commit comments