Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block SSH shell access to git repositories #374

Merged
merged 13 commits into from
Sep 1, 2020
2 changes: 1 addition & 1 deletion scripts/post-receive
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ git clean -f
git checkout master
git branch -D prod
npm install
pm2 startOrRestart deploy.config.js --env production --update-env
sudo -u myproxy pm2 startOrRestart deploy.config.js --env production --update-env
13 changes: 13 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,27 @@ if [ ! -d "./acme.sh" ] ; then
cd ../
fi
if [ ! -d "/home/myproxy" ] ; then
# Add users
sudo useradd -m -c "myproxy" myproxy -s /bin/bash -p $(echo $ADMIN | openssl passwd -1 -stdin) -d "/home/myproxy"
sudo useradd -m -G myproxy -s $(which git-shell) -p $(echo $ADMIN | openssl passwd -1 -stdin) git
# Add sudoers rule for git user to run pm2 as myproxy, without password
echo "git ALL = (myproxy) NOPASSWD: /usr/bin/pm2" > /etc/sudoers.d/git
# Create folders
mkdir /home/myproxy/.ssh
mkdir /home/git/.ssh
mkdir /home/myproxy/.scripts
# Copy ssh keys and scripts
cp ~/.ssh/authorized_keys /home/myproxy/.ssh/authorized_keys
cp ~/.ssh/authorized_keys /home/git/.ssh/authorized_keys
cp ./scripts/post-receive /home/myproxy/.scripts/post-receive
cp ./scripts/pre-receive /home/myproxy/.scripts/pre-receive
cp ./scripts/gitignore /home/myproxy/.scripts/.gitignore
# fix file permissions
chown myproxy:myproxy -R /home/myproxy/
chown git:git -R /home/git/
chmod 2775 -R /home/myproxy/
# Prepend ssh options for authorized keys
sed -i '/^ssh-rsa/s/^/no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty /' /home/git/.ssh/authorized_keys
fi
npm run build
if [ ! -f "./data.db" ] ; then
Expand Down
17 changes: 13 additions & 4 deletions src/api/mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../lib/data'
import { Mapping } from '../types/general'
import prodConfigure from '../../scripts/prod.config.js'
import { getGitUserId } from '../helpers/getGitUser'
import { getGitUserId, getGitGroupId } from '../helpers/getGitUser'
import environment from '../helpers/environment'
const mappingRouter = express.Router()
const exec = util.promisify(cp.exec)
Expand Down Expand Up @@ -61,7 +61,7 @@ mappingRouter.post('/', async (req, res) => {
port: req.body.port || `${portCounter}`,
ip: req.body.ip || '127.0.0.1',
id: uuid4(),
gitLink: `myproxy@${req.body.domain}:${WORKPATH}/${fullDomain}`,
gitLink: `git@${req.body.domain}:${WORKPATH}/${fullDomain}`,
fullDomain
}
domainKeys.push(mappingObject)
Expand All @@ -72,9 +72,14 @@ mappingRouter.post('/', async (req, res) => {
if (!isProduction()) {
return respond()
}

// get user and group id to execute the commands with the correct permissions
const gitUserId = await getGitUserId()
const gitGroupId = await getGitGroupId()

exec(
`
umask 002
cd ${WORKPATH}
mkdir ${fullDomain}
git init ${fullDomain}
Expand All @@ -88,7 +93,7 @@ mappingRouter.post('/', async (req, res) => {
git add .
git commit -m "Initial Commit"
`,
{ uid: gitUserId }
{ uid: gitUserId, gid: gitGroupId }
)
.then(() => {
respond()
Expand Down Expand Up @@ -126,7 +131,11 @@ mappingRouter.delete('/:id', async (req, res) => {
const deletedDomain = getMappingById(req.params.id)
deleteDomain(deletedDomain.fullDomain)
if (!isProduction()) return res.json(deletedDomain)

// get user and group id to execute the commands with the correct permissions
const gitUserId = await getGitUserId()
const gitGroupId = await getGitGroupId()

exec(
`
cd ${WORKPATH}
Expand All @@ -136,7 +145,7 @@ mappingRouter.delete('/:id', async (req, res) => {
fi
rm -rf ${deletedDomain.fullDomain}
`,
{ uid: gitUserId }
{ uid: gitUserId, gid: gitGroupId }
).then(() => {
res.json(deletedDomain)
})
Expand Down
6 changes: 4 additions & 2 deletions src/helpers/authorizedKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import fs from 'fs'
import environment from '../helpers/environment'

const { isProduction } = environment
const sshOptions =
'no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty'
let authorizedKeys: Array<string> = []

const updateSSHKey = (): void => {
if (isProduction()) {
const file = fs.createWriteStream('/home/myproxy/.ssh/authorized_keys')
const file = fs.createWriteStream('/home/git/.ssh/authorized_keys')
file.on('error', err => {
console.log(err)
})
authorizedKeys.forEach(v => {
file.write(`${v}\n`)
file.write(`${sshOptions} ${v}\n`)
})
file.end()
}
Expand Down
7 changes: 6 additions & 1 deletion src/helpers/getGitUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ const getGitUserId = async (): Promise<number> => {
return parseInt(gitId.stdout, 10)
}

export { getGitUserId }
const getGitGroupId = async (): Promise<number> => {
const gitId = await exec('getent group myproxy | cut -d: -f3')
return parseInt(gitId.stdout, 10)
}

export { getGitUserId, getGitGroupId }