Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

GitHub Actions for executing remote SSH commands on Microsoft Windows

The provided code snippets demonstrate a robust CI/CD pipeline for deploying notepad++ using Ansible and GitHub Actions. This setup enables automated deployment of software applications on a Windows virtual machine (VM).

Key Components
Ansible Playbook: The playbook defines tasks for deploying Notepad++ on a Windows VM. It uses the win_shell module to execute PowerShell commands, which map a network drive and install the application.
GitHub Actions Workflow: The workflow automates the deployment process by checking out code, logging in to Azure, setting up Ansible and pywinrm, configuring SSH keys, and running the Ansible playbook.

How it Works

  1. The GitHub Actions workflow is triggered on push events.
  2. The workflow logs in to Azure using a service principal and sets up Ansible and pywinrm.
  3. It configures SSH keys and adds the target VM to the known hosts.
  4. The workflow creates an Ansible inventory file with the VM's details.
  5. Finally, it runs the Ansible playbook, which deploys Notepad++ on the Windows VM.

Microsoft Windows OpenSSH configuration run remote SSH commands Github.com github actions workflows devops ansible yaml yml.png

Benefits
Automation: The pipeline automates the deployment process, reducing manual effort and errors.
Consistency: The Ansible playbook ensures consistent configuration across environments.
Scalability: The pipeline can be easily scaled to deploy multiple applications and environments.

Related Articles
Part 1: OpenSSH Server configuration for Windows
Part 2: Key based passwordless authentication to Microsoft Windows OpenSSH Server
Part 3: Configuring Ansible to Manage Windows Servers via OpenSSH

Here is my Ansible YML code which will be executed on remote Azure virtual machine through GitHub Actions Workflow.

Download this GitHub Actions workflow and ansible code here or it is also available on github.com.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
---
- hosts: vm01
  gather_facts: no
  vars:
    MAPDRIVE_USER: "{{ MAPDRIVE_USER }}"
    MAPDRIVE_SECRET: "{{ MAPDRIVE_SECRET }}"
  tasks:
    - name: SHOW MAPDRIVE_USER
      debug:
        var: MAPDRIVE_USER

    # - name: add directory
    #   win_file:
    #     path: C:\apps
    #     state: directory

    # - name: Download the notepad++ installer
    #   win_get_url:
    #     url: https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.7.8/npp.8.7.8.Installer.x64.exe
    #     dest: C:\apps\npp.8.7.8.Installer.x64.exe
    #     force: true

    - name: Install notepad++
      win_shell: |
        $secpasswd = ConvertTo-SecureString '{{ MAPDRIVE_SECRET }}' -AsPlainText -Force
        $username = 'localhost\{{ MAPDRIVE_USER }}'
        $mycreds = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
        New-PSDrive -Name 'Z' -PSProvider FileSystem -Root '\\vcloudlabdemoscripts.file.core.windows.net\apps' -Credential $mycreds
        Z:\npp.8.7.8.Installer.x64.exe /S

In this configuration I need not to maintain and setup separate Ansible server. I can easily maintain and push code and see the automated output through GitHub actions. The variables mentioned inside the CI/CD GitHub actions workflow yaml codes is already added to secrets which has required sensitive information.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
name: CI/CD Pipeline for Teamcenter Deployment Center

on: [ push ]
  # workflow_dispatch:
  # push:
  #   branches:
  #   - dev # Trigger the pipeline on pushes to the main branch

permissions:
  id-token: write
  contents: read

jobs:
  deployment-center:
    runs-on: ubuntu-latest # Use the github-hosted runner

    env:
      ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
      ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
      ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
      WIN_VM_HOST: "4.246.228.88"  # ${{ secrets.WIN_VM_HOST }} # Private IP of the target Windows VM
      WIN_USER: "azureadmin" # ${{ secrets.WIN_USER }} # Username for the Windows VM
      WIN_PASS: "Computer@123" # ${{ secrets.WIN_PASS }} # Password for the Windows VM
  
    steps:
    # Step 1: Check out the repository
    - name: Checkout code
      uses: actions/checkout@v3

    # Step 2: Log in to Azure using the service principal - OIDC
    - name: Log in to Azure
      uses: azure/login@v2
      with:
        client-id: ${{ secrets.ARM_CLIENT_ID }}
        # client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
        tenant-id: ${{ secrets.ARM_TENANT_ID }}
        subscription-id: ${{ secrets.ARM_SUBSCRIPTION_ID }}

    - name: 'Run az commands'
      run: |
        az account show
        az group list

    # Step 3: Install Ansible and pywinrm
    - name: Set up Ansible and pywinrm
      run: |
        sudo apt-get update
        sudo apt-get install -y ansible python3-pip
        pip3 install pywinrm

    # Step 4: Configure SSH Key
    - name: Configure SSH Key
      run: |
        mkdir -p ~/.ssh
        echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_rsa
        # Add target VM to known_hosts
        ssh-keyscan -t rsa ${{ secrets.WIN_VM_HOST }} >> ~/.ssh/known_hosts
        ssh [email protected] "hostname"

    # Step 5: Configure Ansible Inventory
    - name: Configure Ansible Inventory
      run: |
        echo "[win]" > ansible/inventory
        echo "vm01 ansible_host=${{ env.WIN_VM_HOST }}" >> ansible/inventory
        echo "" >> ansible/inventory
        echo "[win:vars]" >> ansible/inventory
        echo "ansible_user=${{ env.WIN_USER }}" >> ansible/inventory
        echo "ansible_password=${{ env.WIN_PASS }}" >> ansible/inventory
        echo "ansible_connection=ssh" >> ansible/inventory
        echo "ansible_shell_type=cmd" >> ansible/inventory
        echo "ansible_ssh_common_args=-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" >> ansible/inventory
        echo "ansible_ssh_retries=3" >> ansible/inventory
        echo "ansible_become_method=runas" >> ansible/inventory

    # Step 6: Run Ansible Playbook to Deploy Deployment Center
    - name: Deploy Teamcenter using Ansible
      run: |
        ansible-galaxy collection install community.windows
        ansible-galaxy collection install ansible.windows
        ansible-playbook -i ansible/inventory ansible/deploy.yml --extra-vars "MAPDRIVE_USER=${{ secrets.MAPDRIVE_USER }} MAPDRIVE_SECRET=${{ secrets.MAPDRIVE_SECRET }}"

Useful Articles
Part 0: HashiCorp HCP Terraform Cloud backend configuration
Part 1: Create GitHub repository and branches using Terraform
Part 2 Terraform modules using a github.com repository as a source
Part 3 Automating and Planning Azure Resources with Terraform and GitHub Actions
Part 4 GitHub Actions deploy azure resources with Terraform backend
Part 4.1 GitHub Actions deploy azure resources with PowerShell
Part 4.2 GitHub Actions manage Microsoft Azure Cloud with az CLI
Azure OIDC OpenID Connect password less with GitHub Actions
GitHub repository integration with Terraform Cloud to Deploy and Manage Azure
Resolved Terraform Error: POST https api.github.com user repos 401 Requires authentication
Azure DevOps Enable creation of classic build release pipelines grayed out
Adding parameters in Azure DevOps pipelines examples Part 1
Azure Web App Containers Cannot perform credential operations for providers Microsoft.ContainerRegistry ad admin user is disabled, enable it

Go Back

Comment

Blog Search

Page Views

12783665

Follow me on Blogarama