How to grant enough permission for developer on Bastion Host
--
In production environment, the access is private by default, developer usually have not permission to access to the database, search engine, or the running application. In case to debug application, running specific query on database, devops need to provide access for developer to able to access to this resource.
So for each use-case, devops need to grant enough permission. Let go through some use-case.
Use Case 1: Developer need to access to the database.
For this use-case we can provider access to the bastion host and allow user to use ssh port-forwarding only. Let’s do it. Assume you have a virtual machine which has ip 192.168.1.115
and an openssh-server
which is listening on port 2222.
First login to this instance.
ssh root@192.168.1.115 -p 2222
Create user credential for developer.
$ useradd -m -d /home/alice -s /usr/bin/bash alice
Configure openssh server to allow only port-forwarding
cd /etc/ssh
vi sshd_config
add this block to this file
Match User alice
X11Forwarding no
AllowTcpForwarding yes
PermitTTY no
ForceCommand exit
PubkeyAuthentication yes
PasswordAuthentication no
For this configuration, developer only has permission to use port-forwarding, each time use try to login to this server, the user session will be forced to exit. We only support authenticate using public key instead of password to prevent brute force attack.
Let generate a ssh keypair for this user.
❯ ssh-keygen -t ed25519 -f alice -C "alice-user"
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in alice
Your public key has been saved in alice.pub
The key fingerprint is:
SHA256:xeJwT6biReIIn+2GNXp8pveKbLyfP2R58zT5S99xVGM alice-user
The key's randomart image is:
+--[ED25519 256]--+
| |
| . |
| . o + = E.|
| o = * B . o|
| + * S .. ..|
| B + + o +. |
| o.* oo . + =.|
| +o=... o *|
| .=+++o. .+|
+----[SHA256]-----+
~/Desktop/alice-keys on ☁️ (ap-southeast-1)
❯ ll
total 8.0K
-rw------- 1 dong dong 399 Nov 13 11:44 alice
-rw-r--r-- 1 dong dong 92 Nov 13 11:44 alice.pub
~/Desktop/alice-keys on ☁️ (ap-southeast-1)
❯
Now add alice public key to /home/alice/.ssh/authorized_keys
[root@localhost ~]# mkdir -p /home/alice/.ssh
[root@localhost ~]# vi /home/alice/.ssh/authorized_keys
Now, alice
is able to use ssh port-forwarding
but login to this vm, if alice
try to login and get an PTY
session, the session will be terminated.
~/Desktop/alice-keys on ☁️ (ap-southeast-1)
❯ ssh -i alice alice@192.168.1.115 -p 2222
PTY allocation request failed on channel 0
Connection to 192.168.1.115 closed.
Now, let test it. On alice
machine run this command
$ ssh -i alice -N -L 8080:google.com:80 alice@192.168.1.115 -p 2222
Send a request to port 8080
$ curl localhost:8080
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That’s an error.</ins>
<p>The requested URL <code>/</code> was not found on this server. <ins>That’s all we know.</ins>
It works, you can see that we can able to forward port 8080
on local machine to port 80
on host google.com
, you can try with Amazon RDS.
[Security Bug Found, please ignore this ] Use Case 2: Developer need to execute some command to interact with the infrastructure.
This use case is very common, some specific examples like
- Use
aws-cli
to interact with S3 bucket, copy, move, download, etc… - Use
kubectl
to interact with Kubernetes cluster.
Let go with first example, the developer need to access aws s3 bucket
to upload file.
For this use-case, devops have to provide access to the bastion host, installing aws-cli
on this machine then provider ssh credential
to developer so he can able to login.
What devops guys need to restrict here is only provide permission to run aws-cli
for user alice
.
The archive this goal, we can create new directory and storing whitelisted binary that alice
can run, then update PATH
variable for alice
In the SSH configuration section, update alice
setting to this.
Match User alice
X11Forwarding no
AllowTcpForwarding yes
PermitTTY yes
PubkeyAuthentication yes
PasswordAuthentication no
Then restarting the sshd
.
$ systemctl restart sshd
Next, devops config alice
‘s .bash_profile
, binary directory
and PATH
variable.
$ cd /home/alice
$ mkdir bin
$ chown -R alice: /home/alice
$ echo "export PATH=/home/alice/bin" > .bash_profile
$ chown root:root .bash_profile
# this chmod allow alice can read but modified this file.
# this prevent alice change the PATH
$ chmod 664 .bash_profile
Now if alice
login, he will not able to run any command
❯ ssh -i alice alice@192.168.1.115 -p 2222
Last login: Sun Nov 13 12:26:43 2022 from 10.0.2.2
[alice@localhost ~]$ uname -a
bash: uname: command not found...
Packages providing this file are:
'coreutils'
'coreutils-single'
[alice@localhost ~]$
Next step, devops person need to create symbolic link for aws
to /home/alice/bin
[root@localhost ~]# ln -s /usr/local/bin/aws /home/alice/bin/aws
[root@localhost ~]# stat /home/alice/bin/aws
File: /home/alice/bin/aws -> /usr/local/bin/aws
Size: 18 Blocks: 0 IO Block: 4096 symbolic link
Device: fd00h/64768d Inode: 37228668 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:home_bin_t:s0
Access: 2022-11-13 12:32:06.894444010 +0700
Modify: 2022-11-13 12:32:06.894444010 +0700
Change: 2022-11-13 12:32:06.894444010 +0700
Birth: 2022-11-13 12:32:06.894444010 +0700
[root@localhost ~]#
For now, alice
can able to login and executing aws
command.
~/Desktop/alice-keys on ☁️ (ap-southeast-1) took 6m58s
❯ ssh -i alice alice@192.168.1.115 -p 2222
Last login: Sun Nov 13 12:26:52 2022 from 10.0.2.2
[alice@localhost ~]$ aws --version
aws-cli/2.8.12 Python/3.9.11 Linux/5.14.0-183.el9.x86_64 exe/x86_64.centos.9 prompt/off
[alice@localhost ~]$
To provide permission for alice
to run other command, you can use symbolic link
for other binary.