From 7cbae4d58ff3e1003a9e8416271fff8111e046e8 Mon Sep 17 00:00:00 2001 From: konsthol Date: Mon, 29 May 2023 21:46:02 +0300 Subject: [PATCH] Is there an achievement for this? --- harden | 12 ++++++++++-- secdep.py | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/harden b/harden index 999c030..99f3372 100755 --- a/harden +++ b/harden @@ -257,8 +257,12 @@ function kernelSecurityModuleInit { function dockerInit { # Add user to docker group to avoid using sudo when running docker commands sudo usermod -aG docker "$USER" + # Create a new docker network to dissalow communication between containers + sudo docker network create --driver bridge -o "com.docker.network.bridge.enable_icc"="false" dockerNetworkNoICC # Get all arguments passed to the function and store them in the dockerImages array local dockerImages=("$@") + # Check if there is a docker-compose.yml file in the user's home directory + [[ -f "$HOME/docker-compose.yml" ]] && docker-compose -f "$HOME/docker-compose.yml" up -d # If there is, run it # Check if the dockerImages array is empty and return 0 if it is [[ "${#dockerImages[@]}" -eq 0 ]] && return 0 # Loop through the dockerImages array @@ -270,8 +274,12 @@ function dockerInit { # The --security-opt=no-new-privileges option will prevent the docker image from gaining new privileges # The --cap-drop all option will drop all capabilities from the docker image # The --cap-add NET_ADMIN option will add the NET_ADMIN capability to the docker image - docker run -d --restart always --name "$dockerImage" --security-opt=no-new-privileges --cap-drop all --cap-add NET_ADMIN - "$dockerImage" + # The --read-only option will mount the docker image as read-only + # The --tmpfs /opt option will mount the /opt directory as a tmpfs + # The --network dockerNetworkNoICC option will connect the docker image to the dockerNetworkNoICC network + # # The --user secdep option will run the docker image as the secdep user to prevent privilege escalation + docker run -d --restart always --name "$dockerImage" --security-opt=no-new-privileges --cap-drop all --cap-add NET_ADMIN --read-only --tmpfs /opt --network dockerNetworkNoICC "$dockerImage" + #docker run -d --restart always --name "$dockerImage" --security-opt=no-new-privileges --cap-drop all --cap-add NET_ADMIN --user secdep "$dockerImage" done } diff --git a/secdep.py b/secdep.py index e735007..87e4e23 100755 --- a/secdep.py +++ b/secdep.py @@ -47,10 +47,12 @@ pretty.install() # Declare the ENV_FILE variable as such to always reside in the same directory as the script # We use os.path.join to make sure the path is correct for every OS # Also do the same for the ssh keys and the script to be used during deployment +# Finally we declare the docker-compose.yml file in case the user wants to use that in addition to the list of docker images ENV_FILE = os.path.join(os.path.dirname(__file__), ".env") SECDEP_SSH_PUBLIC_KEY = os.path.join(os.path.dirname(__file__), "secdep.pub") SECDEP_SSH_PRIVATE_KEY = os.path.join(os.path.dirname(__file__), "secdep") SECDEP_DEPLOY_SCRIPT = os.path.join(os.path.dirname(__file__), "harden") +SECDEP_DOCKER_COMPOSE = os.path.join(os.path.dirname(__file__), "docker-compose.yml") # Available choices when the action flag is used action_choices = ["delete","start","stop","reboot","deleteall","startall","stopall","rebootall"] @@ -71,6 +73,7 @@ parser.add_argument('-v', '--version', help='Show secdep\'s version', action='st parser.add_argument('-P', '--provider', help='Cloud provider', choices=['gce', 'azure', 'aws']) parser.add_argument('-a', '--action', help='Action to perform on a single provider with -P PROVIDER or all instances. Valid options are delete[all] start[all] stop[all] reboot[all]', choices=action_choices, metavar='ACTION') parser.add_argument('-c', '--create', help='Create an instance', action='store_true') +parser.add_argument('-dc', '--docker-compose', help='Run the docker-compose.yml file', action='store_true') parser.add_argument('-dep', '--deploy', help='Docker images to deploy', type=str, nargs='*', default=None, required=False) parser.add_argument('-I', '--listimages', help='List images', action='store_true') parser.add_argument('-S', '--listsizes', help='List sizes', action='store_true') @@ -1023,10 +1026,15 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi driver.ex_create_firewall(name="allow-all-inbound", allowed=[{"IPProtocol": "tcp", "ports": ["0-65534"]},{"IPProtocol": "udp", "ports": ["0-65534"]}], network='default', direction='INGRESS', priority=1000, source_service_accounts=sa_scopes, target_service_accounts=sa_scopes) if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([sendDockerCompose, actualDeployScript]) + node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + else: + node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") console.print('[bold white]harden stdout: %s[/bold white]' % (actualDeployScript.stdout)) console.print('[bold red]harden stderr: %s[/bold red]' % (actualDeployScript.stderr)) - console. print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) + console.print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) else: node = driver.create_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata) elif provider == "azure": @@ -1080,7 +1088,12 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi # Create the node if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([sendDockerCompose, actualDeployScript]) + node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + else: + node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") console.print('[bold white]harden stdout: %s[/bold white]' % (actualDeployScript.stdout)) console.print('[bold red]harden stderr: %s[/bold red]' % (actualDeployScript.stderr)) console.print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) @@ -1117,7 +1130,11 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi deploy = ScriptDeployment(script=SCRIPT, name="initialization.sh", delete=True) if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - msd = MultiStepDeployment([deploy, actualDeployScript]) + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([deploy, sendDockerCompose, actualDeployScript]) + else: + msd = MultiStepDeployment([deploy, actualDeployScript]) node = driver.deploy_node(name=name, image=image, size=size, ex_keyname=keyname, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_alternate_usernames=["admin", "ec2-user", "centos", "fedora", "ubuntu"]) console.print('[bold white]deploy stdout: %s[/bold white]' % (deploy.stdout)) console.print('[bold red]deploy stderr: %s[/bold red]' % (deploy.stderr)) @@ -1150,10 +1167,15 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi driver.ex_create_firewall(name="allow-all-inbound", allowed=[{"IPProtocol": "tcp", "ports": ["0-65534"]},{"IPProtocol": "udp", "ports": ["0-65534"]}], network='default', direction='INGRESS', priority=1000, source_service_accounts=sa_scopes, target_service_accounts=sa_scopes) if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([sendDockerCompose, actualDeployScript]) + node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + else: + node = driver.deploy_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") console.print('[bold white]harden stdout: %s[/bold white]' % (actualDeployScript.stdout)) console.print('[bold red]harden stderr: %s[/bold red]' % (actualDeployScript.stderr)) - console. print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) + console.print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) else: node = driver.create_node(name=name, image=image, size=size, location=location, ex_service_accounts=sa_scopes, ex_metadata=metadata) elif provider == "azure": @@ -1207,7 +1229,12 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi # Create the node if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([sendDockerCompose, actualDeployScript]) + node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") + else: + node = driver.deploy_node(name=name, size=size, image=image, location=location, auth=auth, ex_user_name="secdep", ex_resource_group=res_group.name, ex_use_managed_disks=True, ex_nic=newnic, ex_os_disk_delete=True, deploy=actualDeployScript, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_username="secdep") console.print('[bold white]harden stdout: %s[/bold white]' % (actualDeployScript.stdout)) console.print('[bold red]harden stderr: %s[/bold red]' % (actualDeployScript.stderr)) console.print('[bold white]harden exit_code: %s[/bold white]' % (actualDeployScript.exit_status)) @@ -1244,7 +1271,11 @@ def create_node(provider, name=None, location=None, size=None, image=None, confi deploy = ScriptDeployment(script=SCRIPT, name="initialization.sh", delete=True) if args.deploy: actualDeployScript = ScriptFileDeployment(script_file=SECDEP_DEPLOY_SCRIPT, args=args.deploy, name="harden", delete=True) - msd = MultiStepDeployment([deploy, actualDeployScript]) + if os.path.exists(SECDEP_DOCKER_COMPOSE) and args.docker-compose: + sendDockerCompose = FileDeployment(SECDEP_DOCKER_COMPOSE, target="/home/secdep") + msd = MultiStepDeployment([deploy, sendDockerCompose, actualDeployScript]) + else: + msd = MultiStepDeployment([deploy, actualDeployScript]) node = driver.deploy_node(name=name, image=image, size=size, ex_keyname=keyname, deploy=msd, ssh_key=SECDEP_SSH_PRIVATE_KEY, ssh_alternate_usernames=["admin", "ec2-user", "centos", "fedora", "ubuntu"]) console.print('[bold white]deploy stdout: %s[/bold white]' % (deploy.stdout)) console.print('[bold red]deploy stderr: %s[/bold red]' % (deploy.stderr)) @@ -1560,6 +1591,9 @@ if args.ssh: if args.image or args.size or args.name or args.region or args.yes or args.deploy and not args.create: console.print("Image, size, name, region, yes and deploy parameters [u]only[/u] go along with the create flag", style="bold red") exit(0) +if args.docker-compose and not args.deploy: + console.print("Docker compose [u]only[/u] goes along with the deploy flag", style="bold red") + exit(0) if args.print and not args.list or args.listimages or args.listsizes or args.listlocations: console.print("The print flag [u]only[/u] goes together with the list, list images, list sizes or list locations", style="bold red") exit(0)