Skip to content

Commit b609111

Browse files
authored
feat: Add git-ssh-mock-server (#3)
2 parents 47c6e28 + f7079f6 commit b609111

File tree

9 files changed

+312
-55
lines changed

9 files changed

+312
-55
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ typings/
5959

6060
# next.js build output
6161
.next
62+
id_rsa
63+
id_rsa.pub
64+
package-lock.json

README.md

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
# git-http-mock-server
1+
# git-http-mock-server / git-ssh-mock-server
22
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fisomorphic-git%2Fgit-http-mock-server.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fisomorphic-git%2Fgit-http-mock-server?ref=badge_shield)
33

4-
5-
Clone and push to git repository test fixtures over HTTP.
4+
Clone and push to git repository test fixtures over HTTP or SSH.
65

76
## What it does
87

@@ -22,6 +21,12 @@ It also supports HTTP Basic Auth password protection of repos so you can test ho
2221

2322
Using `isomorphic-git` and testing things from browsers? Fear not, `git-http-mock-server` includes appropriate CORS headers.
2423

24+
`git-ssh-mock-server` is similar, but because authentication happens before the client can say which repo
25+
they are interested in, the authentication can't be customized per repository.
26+
By default it allows anonymous SSH access. You can disable anonymous access and activate password authentication by setting the `GIT_SSH_MOCK_SERVER_PASSWORD` evironment variable.
27+
(When password auth is activated, any username will work as long as the password matches the environment variable.)
28+
Alternatively, you can set the `GIT_SSH_MOCK_SERVER_PUBKEY` environment variable to true to disable anonymous access and activate Public Key authentication. What key to use is explained in detail later in this document.
29+
2530
## How to use
2631

2732
```sh
@@ -44,6 +49,20 @@ Now in another shell, clone and push away...
4449
> git clone http://localhost:8174/imaginatively-named-repo.git
4550
```
4651

52+
To do the same thing but with SSH
53+
54+
```sh
55+
> cd __fixtures__
56+
> ls
57+
test-repo1.git test-repo2.git imaginatively-named-repo.git
58+
> git-ssh-mock-server
59+
```
60+
61+
Now in another shell,
62+
```sh
63+
> git clone ssh://localhost:2222/imaginatively-named-repo.git
64+
```
65+
4766
## Run in the background
4867

4968
If you want to reuse the same shell (as part of a shell script, for example)
@@ -58,14 +77,27 @@ you can run the server as a daemon in the background:
5877
Just be sure to run `start` and `stop` from the same working directory.
5978
(The `start` command writes the PID of the server to `./git-http-mock-server.pid` so that the `stop` command knows what process to kill.)
6079

80+
Same thing for SSH:
81+
82+
```sh
83+
> git-ssh-mock-server start
84+
> # do stuff
85+
> git-ssh-mock-server stop
86+
```
87+
6188
### Environment Variables
6289

6390
- `GIT_HTTP_MOCK_SERVER_PORT` default is 8174 (to be compatible with [git-http-server](https://github.com/bahamas10/node-git-http-server))
6491
- `GIT_HTTP_MOCK_SERVER_ROUTE` default is `/`
6592
- `GIT_HTTP_MOCK_SERVER_ROOT` default is `process.cwd()`
6693
- `GIT_HTTP_MOCK_SERVER_ALLOW_ORIGIN` default is `*` (used for CORS)
94+
- `GIT_SSH_MOCK_SERVER_PORT` default is 2222
95+
- `GIT_SSH_MOCK_SERVER_ROUTE` default is `/`
96+
- `GIT_SSH_MOCK_SERVER_ROOT` default is `process.cwd()`
97+
- `GIT_SSH_MOCK_SERVER_PASSWORD` activate Password Authentication and use this password (leave blank to allow anonymous SSH access.)
98+
- `GIT_SSH_MOCK_SERVER_PUBKEY` activate PubKey Authentication using the self-generated keypair (leave blank to allow anonymous SSH access.)
6799

68-
### .htpasswd support
100+
### .htpasswd support (http-only)
69101

70102
You can place an Apache-style `.htpasswd` file in a bare repo to protect it with Basic Authentication.
71103

@@ -80,23 +112,41 @@ testuser:$apr1$BRdvH4Mu$3HrpeyBrWiS88GcSPidgq/
80112
If you don't have `htpasswd` on your machine, you can use [htpasswd](https://npm.im/htpasswd) which is
81113
a cross-platform Node implementation of `htpasswd`.
82114

115+
### Public Key Auth support (ssh-only)
116+
117+
`git-ssh-mock-server` generates its own keypair using the system's native `ssh-keygen` the first time it's run,
118+
in order to create encrypted SSH connections.
119+
This key can be used to authenticate with the server as well!
120+
121+
1. Run `GIT_SSH_MOCK_SERVER_PUBKEY=true git-ssh-mock-server`
122+
2. Try cloning (e.g. `git clone ssh://localhost:2222/imaginatively-named-repo.git`). It shouldn't work.
123+
2. Run `git-ssh-mock-server exportKeys` which will copy the key files to `./id_rsa` and `./id_rsa.pub` in the working directory with the correct file permissions (`600`).
124+
3. Run `ssh-add ./id_rsa`
125+
4. Now try cloning. It works!
126+
5. To clear the key from the ssh-agent, use `ssh-add -d ./id_rsa`
127+
128+
You can use `GIT_SSH_MOCK_SERVER_PUBKEY` and `GIT_SSH_MOCK_SERVER_PASSWORD` together, but using either one disables anonymous SSH access.
129+
83130
## Dependencies
84131

85132
- [basic-auth](https://ghub.io/basic-auth): node.js basic auth parser
133+
- [buffer-equal-constant-time](https://ghub.io/buffer-equal-constant-time): Constant-time comparison of Buffers
86134
- [chalk](https://ghub.io/chalk): Terminal string styling done right
87135
- [fixturez](https://ghub.io/fixturez): Easily create and maintain test fixtures in the file system
88136
- [git-http-backend](https://ghub.io/git-http-backend): serve a git repository over http
89137
- [htpasswd-js](https://ghub.io/htpasswd-js): Pure JS htpasswd authentication
138+
- [ssh2](https://ghub.io/ssh2): SSH2 client and server modules written in pure JavaScript for node.js
90139

91140
originally inspired by '[git-http-server](https://github.com/bahamas10/node-git-http-server)'
92141

93142
## License
94143

95144
MIT
96145

97-
98146
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fisomorphic-git%2Fgit-http-mock-server.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fisomorphic-git%2Fgit-http-mock-server?ref=badge_large)
99147

100148
## Changelog
101149

150+
1.2.0 - add SSH server
151+
1.1.0 - support running in background and CORS headers
102152
1.0.0 - Initial release

daemon.js

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,57 @@ const {spawn} = require('child_process')
55
const kill = require('tree-kill')
66
const minimisted = require('minimisted')
77

8-
const cmdName = 'git-http-mock-server'
9-
const target = require.resolve('./bin.js')
10-
const args = [
11-
target
12-
]
8+
module.exports = function (cmdName, target) {
9+
const args = [
10+
target
11+
]
1312

14-
async function main({_: [cmd]}) {
15-
switch (cmd) {
16-
case 'start': {
17-
require('daemonize-process')()
18-
let server = spawn(
19-
'node', args,
20-
{
21-
stdio: 'inherit',
22-
windowsHide: true,
23-
}
24-
)
25-
fs.writeFileSync(
26-
path.join(process.cwd(), `${cmdName}.pid`),
27-
String(process.pid),
28-
'utf8'
29-
)
30-
process.on('exit', server.kill)
31-
return
32-
}
33-
case 'stop': {
34-
let pid
35-
try {
36-
pid = fs.readFileSync(
13+
async function main({_: [cmd]}) {
14+
switch (cmd) {
15+
case 'start': {
16+
require('daemonize-process')()
17+
let server = spawn(
18+
'node', args,
19+
{
20+
stdio: 'inherit',
21+
windowsHide: true,
22+
}
23+
)
24+
fs.writeFileSync(
3725
path.join(process.cwd(), `${cmdName}.pid`),
26+
String(process.pid),
3827
'utf8'
39-
);
40-
} catch (err) {
41-
console.log(`No ${cmdName}.pid file`)
28+
)
29+
process.on('exit', server.kill)
4230
return
4331
}
44-
pid = parseInt(pid)
45-
console.log('killing', pid)
46-
kill(pid, (err) => {
47-
if (err) {
48-
console.log(err)
49-
} else {
50-
fs.unlinkSync(path.join(process.cwd(), `${cmdName}.pid`))
32+
case 'stop': {
33+
let pid
34+
try {
35+
pid = fs.readFileSync(
36+
path.join(process.cwd(), `${cmdName}.pid`),
37+
'utf8'
38+
);
39+
} catch (err) {
40+
console.log(`No ${cmdName}.pid file`)
41+
return
5142
}
52-
})
53-
return
54-
}
55-
default: {
56-
require(target)
43+
pid = parseInt(pid)
44+
console.log('killing', pid)
45+
kill(pid, (err) => {
46+
if (err) {
47+
console.log(err)
48+
} else {
49+
fs.unlinkSync(path.join(process.cwd(), `${cmdName}.pid`))
50+
}
51+
})
52+
return
53+
}
54+
default: {
55+
require(target)
56+
}
5757
}
5858
}
59-
}
60-
61-
minimisted(main)
59+
60+
minimisted(main)
61+
}

http-daemon.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env node
2+
const cmdName = 'git-http-mock-server'
3+
const target = require.resolve('./http-server.js')
4+
require('./daemon.js')(cmdName, target)

bin.js renamed to http-server.js

File renamed without changes.

package-lock.json

Lines changed: 55 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "Clone and push to git repository test fixtures over HTTP.",
55
"main": "index.js",
66
"bin": {
7-
"git-http-mock-server": "daemon.js"
7+
"git-http-mock-server": "http-daemon.js",
8+
"git-ssh-mock-server": "ssh-daemon.js"
89
},
910
"scripts": {
1011
"test": "echo \"No tests\"",
@@ -29,14 +30,17 @@
2930
"homepage": "https://github.com/isomorphic-git/git-http-mock-server#readme",
3031
"dependencies": {
3132
"basic-auth": "^2.0.0",
33+
"buffer-equal-constant-time": "^1.0.1",
3234
"chalk": "^2.4.1",
3335
"daemonize-process": "^1.0.9",
3436
"fixturez": "^1.1.0",
3537
"git-http-backend": "^1.0.2",
3638
"htpasswd-js": "^1.0.2",
3739
"micro-cors": "^0.1.1",
3840
"minimisted": "^2.0.0",
39-
"tree-kill": "^1.2.0"
41+
"tree-kill": "^1.2.0",
42+
"ssh-keygen": "^0.4.2",
43+
"ssh2": "^0.6.1"
4044
},
4145
"devDependencies": {
4246
"semantic-release": "15.1.7",

ssh-daemon.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env node
2+
const cmdName = 'git-ssh-mock-server'
3+
const target = require.resolve('./ssh-server.js')
4+
require('./daemon.js')(cmdName, target)

0 commit comments

Comments
 (0)