Ansible-Powered DevSecOps: Automating Secure CI/CD Pipelines Without Jenkins or GitHub Actions + Video

Listen to this Post

Featured Image

Introduction:

Modern DevSecOps demands automation that embeds security from the first line of code to the final container deployment. While many organizations rely on complex CI/CD tools like Jenkins or GitHub Actions, a streamlined approach using Ansible can provision infrastructure, enforce security gates, and deploy applications with idempotent reliability. This article dissects a production-ready pipeline that transforms three bare EC2 instances into a fully automated, security-scanned container deployment—all driven by two Ansible playbooks and a strict “fail fast” philosophy.

Learning Objectives:

  • Implement an end-to-end CI/CD pipeline using only Ansible for infrastructure provisioning, configuration management, and deployment.
  • Integrate static code analysis (SonarQube) and container vulnerability scanning (Trivy) as mandatory security gates.
  • Automate SSH fingerprint management to eliminate manual intervention when scaling to hundreds of target nodes.
  • Build idempotent deployment strategies that ensure consistent application state across multiple environments.

You Should Know:

  1. Automating SSH Host Key Verification for Zero-Touch Provisioning

When Ansible connects to a new EC2 instance, the default SSH behavior prompts the user to accept the host’s fingerprint. Manually typing “yes” for each target breaks automation at scale. The solution involves pre-populating the `known_hosts` file using `ssh-keyscan` before executing any playbook.

Step‑by‑step guide:

  1. After launching EC2 instances, retrieve their public IPs or DNS names.
  2. Use `ssh-keyscan` to fetch and store host keys without manual confirmation.
    For each target IP, add its key to the Ansible controller's known_hosts
    ssh-keyscan -H 192.168.1.10 >> ~/.ssh/known_hosts
    ssh-keyscan -H 192.168.1.11 >> ~/.ssh/known_hosts
    

3. Alternatively, loop through an inventory file:

while read ip; do ssh-keyscan -H "$ip" >> ~/.ssh/known_hosts; done < inventory.txt

4. Verify that Ansible can now connect without prompts:

ansible all -i inventory.ini -m ping

This step is critical for CI/CD pipelines where new ephemeral instances are created per build.

2. Multi-Target Tool Installation with Idempotent Playbooks

A single Ansible playbook (install-tools.yml) ensures all target nodes have identical toolchains: OpenJDK 17, Maven, Docker, SonarQube container, SonarScanner, and Trivy. Idempotency guarantees that repeated runs do not break existing installations.

Step‑by‑step guide:

  • Define tasks that check for existing installations before executing changes.
  • Example task for Docker installation and permission hardening:
    </li>
    <li>name: Install Docker
    apt:
    name: docker.io
    state: present
    notify: start docker</p></li>
    <li><p>name: Set Docker socket permissions
    file:
    path: /var/run/docker.sock
    mode: '0666'
    

  • Use handlers to start services only when changes occur.
  • For SonarQube, deploy as a container to keep dependencies isolated:
    </li>
    <li>name: Run SonarQube container
    docker_container:
    name: sonarqube
    image: sonarqube:latest
    ports:</li>
    <li>"9000:9000"
    restart_policy: always
    
  • Verify installations with ad-hoc commands:
    ansible targets -m command -a "java -version"
    ansible targets -m command -a "docker --version"
    

3. Git Repository Synchronization for Continuous Code Updates

To ensure target nodes always reflect the latest source code, the pipeline uses `git clone` on the first run and `git pull` on subsequent executions. This eliminates the need for manual code transfers or external artifact repositories.

Step‑by‑step guide:

  • Implement a task that checks for the existence of the repository directory.
    </li>
    <li>name: Clone repo if not present
    git:
    repo: https://github.com/username/repo.git
    dest: /opt/app
    when: not repo_exists.stat.exists</p></li>
    <li><p>name: Pull latest changes
    git:
    repo: https://github.com/username/repo.git
    dest: /opt/app
    update: yes
    

  • Use a `stat` module to test directory existence before deciding which action to take.
  • This approach ensures that every playbook run operates on the current commit, enabling continuous delivery without manual triggers.

4. Compilation, Unit Testing, and Fail-Fast Gates

Before any packaging or deployment, the pipeline compiles the code and executes unit tests. If tests fail, the entire pipeline halts—preventing broken code from advancing to security scans or production.

Step‑by‑step guide:

  • Execute Maven commands with error handling.
    </li>
    <li>name: Compile source code
    command: mvn compile
    args:
    chdir: /opt/app
    register: compile_result
    failed_when: compile_result.rc != 0</p></li>
    <li><p>name: Run unit tests
    command: mvn test
    args:
    chdir: /opt/app
    register: test_result
    failed_when: test_result.rc != 0
    

  • The `failed_when` directive ensures Ansible stops immediately on failure.
  • This “fail fast” principle saves time and resources by catching issues early.

5. SonarQube Static Analysis with Secrets Management

Static code analysis is enforced via SonarQube, with credentials securely stored in Ansible Vault. The project must pass the Quality Gate before proceeding; otherwise, the pipeline aborts.

Step‑by‑step guide:

  • Encrypt sensitive data using Ansible Vault.
    ansible-vault encrypt_string 'your_sonar_token' --name 'sonar_token'
    
  • Include the encrypted variables in your playbook.
  • Run SonarScanner via the container:
    </li>
    <li>name: Run SonarQube analysis
    command: >
    docker run --rm
    -v /opt/app:/usr/src
    sonarsource/sonar-scanner-cli
    -Dsonar.projectKey=my_project
    -Dsonar.host.url={{ sonar_url }}
    -Dsonar.login={{ sonar_token }}
    
  • After analysis, query the Quality Gate status. If failed, halt the pipeline.

6. Building the JAR and Docker Image

With passing tests and quality gates, the pipeline compiles a JAR, builds a Docker image, and tags it for deployment. All steps remain idempotent.

Step‑by‑step guide:

  • Use Maven to package the application.
    </li>
    <li>name: Build JAR
    command: mvn package -DskipTests
    args:
    chdir: /opt/app
    
  • Build the Docker image using the Dockerfile in the repository.
    </li>
    <li>name: Build Docker image
    docker_image:
    name: myapp:latest
    build:
    path: /opt/app
    source: build
    
  • Tag the image with a version (e.g., build number) for traceability.

7. Trivy Container Vulnerability Scanning

Before pushing to Docker Hub, the image undergoes a comprehensive vulnerability scan using Trivy. An HTML report is generated per target, providing an audit trail.

Step‑by‑step guide:

  • Install Trivy if not already present.
    wget https://github.com/aquasecurity/trivy/releases/download/v0.18.3/trivy_0.18.3_Linux-64bit.deb
    sudo dpkg -i trivy_0.18.3_Linux-64bit.deb
    
  • Run the scan and generate an HTML report.
    </li>
    <li>name: Scan image with Trivy
    command: trivy image --format template --template "@contrib/html.tpl" -o trivy_report.html myapp:latest
    
  • Fail the playbook if critical vulnerabilities are found:
    </li>
    <li>name: Fail if critical vulnerabilities detected
    fail:
    msg: "Critical vulnerabilities found. Aborting deployment."
    when: "'CRITICAL' in trivy_report.stdout"
    

8. Pushing to Docker Hub and Idempotent Deployment

The final stage authenticates to Docker Hub, pushes the scanned image, and deploys it idempotently—stopping the old container and launching the new one only if the image has changed.

Step‑by‑step guide:

  • Authenticate to Docker Hub using Vault-stored credentials.
    </li>
    <li>name: Login to Docker Hub
    docker_login:
    registry_url: https://index.docker.io/v1/
    username: "{{ docker_hub_user }}"
    password: "{{ docker_hub_token }}"
    
  • Push the image:
    </li>
    <li>name: Push image to Docker Hub
    docker_image:
    name: myapp:latest
    repository: username/myapp:latest
    push: yes
    source: local
    
  • Deploy idempotently:
    </li>
    <li>name: Stop and remove old container
    docker_container:
    name: myapp
    state: absent</p></li>
    <li><p>name: Run new container
    docker_container:
    name: myapp
    image: username/myapp:latest
    state: started
    ports:</p></li>
    <li>"8080:8080"
    

What Undercode Say:

  • Automation without CI/CD bloat: Ansible can replace heavyweight CI/CD tools for many use cases, proving that simplicity and idempotency often trump complex orchestration.
  • Security gates are non-negotiable: Embedding SonarQube static analysis and Trivy container scans directly into the provisioning pipeline ensures that security is not an afterthought.
  • SSH key management is foundational: Pre-populating `known_hosts` with `ssh-keyscan` is a small but critical step that enables true scale—without it, automation fails at the first manual prompt.
  • Idempotency is the key to reliability: Every playbook task must be written to safely run multiple times, ensuring that infrastructure remains in the desired state regardless of execution frequency.

Prediction:

As organizations continue to adopt infrastructure-as-code principles, we will see a rise in Ansible-native CI/CD pipelines that treat security scans as first-class citizens. The trend will move away from monolithic CI/CD platforms toward composable, lightweight automation stacks that integrate vulnerability scanning, compliance checks, and deployment in a single workflow. Expect tooling to evolve with tighter integration between configuration management, container security, and cloud-native secret management—making DevSecOps pipelines more accessible to teams without dedicated platform engineering resources.

▶️ Related Video (86% Match):

🎯Let’s Practice For Free:

IT/Security Reporter URL:

Reported By: Zoumana Ouattara – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow UndercodeTesting & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin | 🦋BlueSky