provider-ssh

module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2025 License: Apache-2.0

README

Provider SSH

Overview

The provider-ssh is a Crossplane provider that reconciles external resources reachable over SSH. It executes user-supplied scripts to converge a remote system to a desired state, exposes observed state from checks, and supports idempotency and drift detection.

Kinds
  • ProviderConfig: to authenticate/reach the target(s)
  • SSHTask: A unit of desired work on a host

Installation

You can run the provider-ssh locally or install it from an xpkg file. To install the provider use:

apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-ssh
spec:
  package: docker.io/etesami/provider-ssh:latest

ProviderConfig

To begin, you'll need to create a ProviderConfig and a Secret. To initiate a connection to the remote host, either a password or privateKey is required. The privateKey should be provided as a single-line, base64-encoded string. To generate the base64 version of a private key, use the following command:

# In Linux
cat .ssh/id_rsa | base64 -w0

The knownHosts file is required to verify the identity of the server. You can generate and verify it using the command below:

ssh-keyscan <HOST-REMOTE-IP>

Next, construct the ProviderConfig and Secret as shown below:

apiVersion: v1
kind: Secret
metadata:
  namespace: crossplane-system
  name: providerssh-secret
type: Opaque
stringData:
  config: |
    {
      "username": "ubuntu",
      "password": "password",
      "privateKey": "5XUUNPV2tSd0ptTFp...wbTNFKzhqMkYzdXc5ClNRZ09QO",
      "hostIP": "10.29.30.5",
      "hostPort": "22",
      "knownHosts": "10.29.30.5 ecdsa-sha2-nistp256 AAAAE2VjZHN...UpvT57WP45MDBAV4CxQ="
    }
---
apiVersion: ssh.crossplane.io/v1alpha1
kind: ProviderConfig
metadata:
  name: providerssh-config
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: providerssh-secret
      key: config

SSHTask

apiVersion: ssh.crossplane.io/v1alpha1
kind: SSHTask
metadata:
  name: configure-nginx
spec:
  providerConfigRef:
    name: default
  managementPolicies: ["*"]
  forProvider:
    scripts:

      # 1) PROBE: collect facts + compliance + optional drift (JSON)
      # Probe: check compliance + collect facts
      probeScript:
        inline: |
          set -euo pipefail
          compliant=true
          if ! command -v nginx >/dev/null 2>&1; then
            compliant=false
          fi
          version=""
          if $compliant; then
            version=$(nginx -v 2>&1 | cut -d'/' -f2)
          fi
          jq -n --argjson c $compliant --arg v "$version" \
            '{facts:{nginx:{version:$v}},compliant:$c}'

      # Ensure: install nginx
      ensureScript:
        inline: |
          set -euo pipefail
          sudo apt-get update -y
          sudo apt-get install -y nginx jq

      # Cleanup: remove nginx
      cleanupScript:
        inline: |
          sudo apt-get purge -y nginx || true

    observe:
      refreshPolicy: Always          # probe every reconcile
      freshnessTTL: 60s              # ignored with Always
      capture: stdout
      map:
        - from: $.nginx.version
          to: version

    # Execution environment & safety
    execution:
      sudo: true
      shell: /bin/bash -euo pipefail
      timeoutSeconds: 600
      maxAttempts: 2              # per reconcile
      # env is map of key, values where all instance of key is replaced
      # by value before executing the script on the remove device
      env:
        INLINE_VAR: FOO

    artifactPolicy:
      capture: stdout        # stdout | stderr | both | none
        
      
status:
  conditions:
    - type: Ready
      status: "True"
      reason: UpToDate
      lastTransitionTime: "2025-08-18T14:02:31Z"
    - type: Synced
      status: "True"
      reason: ObserveSucceeded
      lastTransitionTime: "2025-08-18T14:02:31Z"
  atProvider:
    endpoint:
      host: "10.0.0.12"
      port: 22
      username: "ubuntu"
    lastCheckTime: "2025-08-18T14:02:29Z"
    lastRun:
      time: "2025-08-18T14:02:29Z"
      exitCode: 0
      retryCount: 0
    artifacts:
      stdout: ""
      stderr: ""
    observed:
      raw: {}                # the full JSON payload (optional, gated by size limit)
      fields:                # mapped key/value facts
        version: "1.24.0"
        indexETag: "d41d8cd98f00b204e9800998ecf8427e"
      digest: "sha256:..."   # hash of observe payload for cheap change detection
      observedAt: "..."      # RFC3339
    

Controller Logic

Observe
  • If no probeScript → Resource is not up to date, requeue for update
  • If resource is current (not stale) → mark as Ready
  • Run probeScript, save artifact
    • If failed → requeue for update
    • If successful → parse output (digest + field mapping)
      • If compliant → mark as Ready
      • If not compliant → requeue for update
Update
  • If no ensureScript → reconcile error
  • Run ensureScript, save artifact
    • If failed → reconcile error, mark as Not Ready
    • If successful → run probeScript again
      • If failed → Ready = false, requeue
      • If successful → process output
        • Save to status.observed
        • If compliant → Done
        • If not compliant → return empty

Development

make build
# The image is stored somewhere like
pkg=provider-ssh-v0.0.0-21.gb69de81.xpkg
VERSION=v2.0.0-rc6 && \
  DIR=/home/ubuntu/provider-ssh/_output/xpkg/linux_amd64 && \
  crossplane xpkg push -f $DIR/$pkg index.docker.io/etesami/provider-ssh:$VERSION && \
  crossplane xpkg push -f $DIR/$pkg index.docker.io/etesami/provider-ssh:latest

Directories

Path Synopsis
Package apis contains Kubernetes API for the SSH provider.
Package apis contains Kubernetes API for the SSH provider.
v1alpha1
Package v1alpha1 contains the core resources of the SSH provider.
Package v1alpha1 contains the core resources of the SSH provider.
cmd
provider command
internal
version
Package version contains the version of this repo
Package version contains the version of this repo

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL