up
Some checks failed
LNM Migration CI / build-runner (push) Has been cancelled
Ledger OpenAPI CI / deprecation-check (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Airgap Sealed CI Smoke / sealed-smoke (push) Has been cancelled
Ledger Packs CI / build-pack (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Ledger OpenAPI CI / validate-oas (push) Has been cancelled
Ledger OpenAPI CI / check-wellknown (push) Has been cancelled
Ledger Packs CI / verify-pack (push) Has been cancelled
LNM Migration CI / validate-metrics (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Some checks failed
LNM Migration CI / build-runner (push) Has been cancelled
Ledger OpenAPI CI / deprecation-check (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Airgap Sealed CI Smoke / sealed-smoke (push) Has been cancelled
Ledger Packs CI / build-pack (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Ledger OpenAPI CI / validate-oas (push) Has been cancelled
Ledger OpenAPI CI / check-wellknown (push) Has been cancelled
Ledger Packs CI / verify-pack (push) Has been cancelled
LNM Migration CI / validate-metrics (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
This commit is contained in:
181
deploy/ansible/README.md
Normal file
181
deploy/ansible/README.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Zastava Agent Ansible Deployment
|
||||
|
||||
Ansible playbook for deploying StellaOps Zastava Agent on VM/bare-metal hosts.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Ansible 2.10 or later
|
||||
- Target hosts must have:
|
||||
- Docker installed and running
|
||||
- SSH access with sudo privileges
|
||||
- systemd as init system
|
||||
- Internet access (for downloading agent binaries) OR local artifact repository
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Create inventory file:**
|
||||
|
||||
```bash
|
||||
cp inventory.yml.sample inventory.yml
|
||||
```
|
||||
|
||||
2. **Edit inventory with your hosts and configuration:**
|
||||
|
||||
```yaml
|
||||
zastava_agents:
|
||||
hosts:
|
||||
your-host:
|
||||
ansible_host: 192.168.1.100
|
||||
ansible_user: ubuntu
|
||||
vars:
|
||||
zastava_tenant: your-tenant
|
||||
scanner_backend_url: https://scanner.internal
|
||||
```
|
||||
|
||||
3. **Run the playbook:**
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.yml zastava-agent.yml
|
||||
```
|
||||
|
||||
## Configuration Variables
|
||||
|
||||
### Required Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `zastava_tenant` | Tenant identifier for multi-tenancy isolation |
|
||||
| `scanner_backend_url` | URL of the Scanner backend service |
|
||||
|
||||
### Optional Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `zastava_version` | `latest` | Agent version to deploy |
|
||||
| `zastava_node_name` | hostname | Override node name in events |
|
||||
| `zastava_health_port` | `8080` | Health check HTTP port |
|
||||
| `docker_socket` | `/var/run/docker.sock` | Docker socket path |
|
||||
| `zastava_log_level` | `Information` | Serilog log level |
|
||||
| `scanner_backend_insecure` | `false` | Allow HTTP backend (NOT for production) |
|
||||
| `download_base_url` | `https://releases.stellaops.org` | Base URL for agent downloads |
|
||||
|
||||
### Advanced Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `zastava_extra_env` | Dictionary of additional environment variables |
|
||||
|
||||
## Directory Structure
|
||||
|
||||
After deployment, the agent is installed with the following structure:
|
||||
|
||||
```
|
||||
/opt/stellaops/zastava-agent/ # Agent binaries
|
||||
/etc/stellaops/zastava-agent.env # Environment configuration
|
||||
/var/lib/zastava-agent/ # Data directory
|
||||
/var/lib/zastava-agent/runtime-events/ # Event buffer (disk-backed)
|
||||
/etc/systemd/system/zastava-agent.service # systemd unit
|
||||
```
|
||||
|
||||
## Post-Deployment Verification
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
systemctl status zastava-agent
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
journalctl -u zastava-agent -f
|
||||
```
|
||||
|
||||
### Health Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
|----------|-------------|
|
||||
| `/healthz` | Liveness probe - agent is running |
|
||||
| `/readyz` | Readiness probe - agent can process events |
|
||||
| `/livez` | Alias for liveness probe |
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/healthz
|
||||
curl http://localhost:8080/readyz
|
||||
```
|
||||
|
||||
## Air-Gapped Deployment
|
||||
|
||||
For air-gapped environments:
|
||||
|
||||
1. Download agent tarball to a local artifact server
|
||||
2. Set `download_base_url` to your local server:
|
||||
|
||||
```yaml
|
||||
download_base_url: https://artifacts.internal/stellaops
|
||||
```
|
||||
|
||||
3. Ensure the URL structure matches:
|
||||
`{download_base_url}/zastava-agent/{version}/zastava-agent-linux-{arch}.tar.gz`
|
||||
|
||||
## Security Notes
|
||||
|
||||
### Docker Socket Access
|
||||
|
||||
The agent requires read access to the Docker socket to monitor container events.
|
||||
The service runs as the `zastava-agent` user in the `docker` group.
|
||||
|
||||
See `docs/modules/zastava/operations/docker-socket-permissions.md` for security
|
||||
considerations and alternative configurations.
|
||||
|
||||
### systemd Hardening
|
||||
|
||||
The service unit includes security hardening:
|
||||
|
||||
- `NoNewPrivileges=true` - Prevent privilege escalation
|
||||
- `ProtectSystem=strict` - Read-only system directories
|
||||
- `PrivateTmp=true` - Isolated /tmp
|
||||
- `ProtectKernelTunables=true` - No kernel parameter modification
|
||||
- Resource limits on file descriptors and memory
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Agent Won't Start
|
||||
|
||||
1. Check Docker service: `systemctl status docker`
|
||||
2. Verify Docker socket permissions: `ls -la /var/run/docker.sock`
|
||||
3. Check agent logs: `journalctl -u zastava-agent -e`
|
||||
|
||||
### Cannot Connect to Backend
|
||||
|
||||
1. Verify network connectivity: `curl -I ${scanner_backend_url}/healthz`
|
||||
2. Check TLS certificates if using HTTPS
|
||||
3. Ensure firewall allows outbound connections
|
||||
|
||||
### Events Not Being Sent
|
||||
|
||||
1. Check event buffer directory permissions
|
||||
2. Verify health endpoint returns healthy: `curl localhost:8080/readyz`
|
||||
3. Check agent logs for connection errors
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To remove the agent:
|
||||
|
||||
```bash
|
||||
# Stop and disable service
|
||||
sudo systemctl stop zastava-agent
|
||||
sudo systemctl disable zastava-agent
|
||||
|
||||
# Remove files
|
||||
sudo rm -rf /opt/stellaops/zastava-agent
|
||||
sudo rm -f /etc/stellaops/zastava-agent.env
|
||||
sudo rm -f /etc/systemd/system/zastava-agent.service
|
||||
sudo rm -rf /var/lib/zastava-agent
|
||||
|
||||
# Remove user
|
||||
sudo userdel zastava-agent
|
||||
|
||||
# Reload systemd
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
58
deploy/ansible/files/zastava-agent.service
Normal file
58
deploy/ansible/files/zastava-agent.service
Normal file
@@ -0,0 +1,58 @@
|
||||
[Unit]
|
||||
Description=StellaOps Zastava Agent - Container Runtime Monitor
|
||||
Documentation=https://docs.stellaops.org/zastava/agent/
|
||||
After=network-online.target docker.service containerd.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/opt/stellaops/zastava-agent/StellaOps.Zastava.Agent
|
||||
WorkingDirectory=/opt/stellaops/zastava-agent
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
# Environment configuration
|
||||
EnvironmentFile=-/etc/stellaops/zastava-agent.env
|
||||
Environment=DOTNET_ENVIRONMENT=Production
|
||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
# User and permissions
|
||||
User=zastava-agent
|
||||
Group=docker
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
|
||||
# Allow read access to Docker socket
|
||||
ReadWritePaths=/var/run/docker.sock
|
||||
ReadWritePaths=/var/lib/zastava-agent
|
||||
|
||||
# Capabilities
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=65536
|
||||
LimitNPROC=4096
|
||||
MemoryMax=512M
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=zastava-agent
|
||||
|
||||
# Watchdog (5 minute timeout)
|
||||
WatchdogSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
46
deploy/ansible/inventory.yml.sample
Normal file
46
deploy/ansible/inventory.yml.sample
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
# Sample Ansible Inventory for Zastava Agent Deployment
|
||||
#
|
||||
# Copy this file to inventory.yml and customize for your environment.
|
||||
# Then run: ansible-playbook -i inventory.yml zastava-agent.yml
|
||||
|
||||
all:
|
||||
children:
|
||||
zastava_agents:
|
||||
hosts:
|
||||
# Add your VM/bare-metal hosts here
|
||||
vm-node-1:
|
||||
ansible_host: 192.168.1.101
|
||||
ansible_user: ubuntu
|
||||
vm-node-2:
|
||||
ansible_host: 192.168.1.102
|
||||
ansible_user: ubuntu
|
||||
# Example with SSH key
|
||||
vm-node-3:
|
||||
ansible_host: 192.168.1.103
|
||||
ansible_user: root
|
||||
ansible_ssh_private_key_file: ~/.ssh/stellaops_key
|
||||
|
||||
vars:
|
||||
# Required: Set these for your environment
|
||||
zastava_tenant: my-tenant
|
||||
scanner_backend_url: https://scanner.example.com
|
||||
|
||||
# Optional: Override node name per host
|
||||
# zastava_node_name: custom-node-name
|
||||
|
||||
# Optional: Change health check port
|
||||
# zastava_health_port: 8080
|
||||
|
||||
# Optional: Custom Docker socket path
|
||||
# docker_socket: /var/run/docker.sock
|
||||
|
||||
# Optional: Set log level (Verbose, Debug, Information, Warning, Error)
|
||||
# zastava_log_level: Information
|
||||
|
||||
# Optional: Allow insecure HTTP (NOT for production)
|
||||
# scanner_backend_insecure: false
|
||||
|
||||
# Optional: Additional environment variables
|
||||
# zastava_extra_env:
|
||||
# CUSTOM_VAR: custom_value
|
||||
40
deploy/ansible/templates/zastava-agent.env.j2
Normal file
40
deploy/ansible/templates/zastava-agent.env.j2
Normal file
@@ -0,0 +1,40 @@
|
||||
# StellaOps Zastava Agent Configuration
|
||||
# Managed by Ansible - Do not edit manually
|
||||
# Generated: {{ ansible_date_time.iso8601 }}
|
||||
|
||||
# Tenant identifier for multi-tenancy
|
||||
ZASTAVA_TENANT={{ zastava_tenant }}
|
||||
|
||||
# Scanner backend URL
|
||||
ZASTAVA_AGENT__Backend__BaseAddress={{ scanner_backend_url }}
|
||||
|
||||
{% if zastava_node_name is defined %}
|
||||
# Node name override
|
||||
ZASTAVA_NODE_NAME={{ zastava_node_name }}
|
||||
{% endif %}
|
||||
|
||||
# Docker socket endpoint
|
||||
ZASTAVA_AGENT__DockerEndpoint=unix://{{ docker_socket }}
|
||||
|
||||
# Event buffer path
|
||||
ZASTAVA_AGENT__EventBufferPath={{ zastava_data_dir }}/runtime-events
|
||||
|
||||
# Health check port
|
||||
ZASTAVA_AGENT__HealthCheck__Port={{ zastava_health_port }}
|
||||
|
||||
{% if scanner_backend_insecure | default(false) | bool %}
|
||||
# WARNING: Insecure HTTP backend enabled
|
||||
ZASTAVA_AGENT__Backend__AllowInsecureHttp=true
|
||||
{% endif %}
|
||||
|
||||
{% if zastava_log_level is defined %}
|
||||
# Logging level
|
||||
Serilog__MinimumLevel__Default={{ zastava_log_level }}
|
||||
{% endif %}
|
||||
|
||||
{% if zastava_extra_env is defined %}
|
||||
# Additional environment variables
|
||||
{% for key, value in zastava_extra_env.items() %}
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
232
deploy/ansible/zastava-agent.yml
Normal file
232
deploy/ansible/zastava-agent.yml
Normal file
@@ -0,0 +1,232 @@
|
||||
---
|
||||
# Ansible Playbook for Zastava Agent VM/Bare-Metal Deployment
|
||||
#
|
||||
# Requirements:
|
||||
# - Target hosts must have Docker installed and running
|
||||
# - Ansible 2.10+ with community.docker collection
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.yml zastava-agent.yml \
|
||||
# -e zastava_tenant=my-tenant \
|
||||
# -e scanner_backend_url=https://scanner.internal
|
||||
#
|
||||
# Variables (can be set in inventory or via -e):
|
||||
# zastava_tenant: Tenant identifier (required)
|
||||
# scanner_backend_url: Scanner backend URL (required)
|
||||
# zastava_version: Version to deploy (default: latest)
|
||||
# zastava_node_name: Override node name (default: hostname)
|
||||
# zastava_health_port: Health check port (default: 8080)
|
||||
# docker_socket: Docker socket path (default: /var/run/docker.sock)
|
||||
|
||||
- name: Deploy StellaOps Zastava Agent
|
||||
hosts: zastava_agents
|
||||
become: true
|
||||
|
||||
vars:
|
||||
zastava_version: "{{ zastava_version | default('latest') }}"
|
||||
zastava_install_dir: /opt/stellaops/zastava-agent
|
||||
zastava_config_dir: /etc/stellaops
|
||||
zastava_data_dir: /var/lib/zastava-agent
|
||||
zastava_user: zastava-agent
|
||||
zastava_group: docker
|
||||
zastava_health_port: "{{ zastava_health_port | default(8080) }}"
|
||||
docker_socket: "{{ docker_socket | default('/var/run/docker.sock') }}"
|
||||
download_base_url: "{{ download_base_url | default('https://releases.stellaops.org') }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate required variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- zastava_tenant is defined and zastava_tenant | length > 0
|
||||
- scanner_backend_url is defined and scanner_backend_url | length > 0
|
||||
fail_msg: |
|
||||
Required variables not set.
|
||||
Please provide:
|
||||
- zastava_tenant: Your tenant identifier
|
||||
- scanner_backend_url: Scanner backend URL
|
||||
|
||||
- name: Check Docker service is running
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
check_mode: true
|
||||
register: docker_status
|
||||
|
||||
- name: Fail if Docker is not available
|
||||
ansible.builtin.fail:
|
||||
msg: "Docker service is not running on {{ inventory_hostname }}"
|
||||
when: docker_status.status.ActiveState != 'active'
|
||||
|
||||
tasks:
|
||||
# =========================================================================
|
||||
# User and Directory Setup
|
||||
# =========================================================================
|
||||
|
||||
- name: Create zastava-agent system user
|
||||
ansible.builtin.user:
|
||||
name: "{{ zastava_user }}"
|
||||
comment: StellaOps Zastava Agent
|
||||
system: true
|
||||
shell: /usr/sbin/nologin
|
||||
groups: "{{ zastava_group }}"
|
||||
create_home: false
|
||||
state: present
|
||||
|
||||
- name: Create installation directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_install_dir }}"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Create configuration directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_config_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Create data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_data_dir }}"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0750'
|
||||
|
||||
- name: Create event buffer directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_data_dir }}/runtime-events"
|
||||
state: directory
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0750'
|
||||
|
||||
# =========================================================================
|
||||
# Download and Install Agent
|
||||
# =========================================================================
|
||||
|
||||
- name: Determine architecture
|
||||
ansible.builtin.set_fact:
|
||||
arch_suffix: "{{ 'x64' if ansible_architecture == 'x86_64' else 'arm64' if ansible_architecture == 'aarch64' else ansible_architecture }}"
|
||||
|
||||
- name: Download Zastava Agent binary
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ download_base_url }}/zastava-agent/{{ zastava_version }}/zastava-agent-linux-{{ arch_suffix }}.tar.gz"
|
||||
dest: /tmp/zastava-agent.tar.gz
|
||||
mode: '0644'
|
||||
register: download_result
|
||||
retries: 3
|
||||
delay: 5
|
||||
|
||||
- name: Extract Zastava Agent
|
||||
ansible.builtin.unarchive:
|
||||
src: /tmp/zastava-agent.tar.gz
|
||||
dest: "{{ zastava_install_dir }}"
|
||||
remote_src: true
|
||||
owner: "{{ zastava_user }}"
|
||||
group: "{{ zastava_group }}"
|
||||
extra_opts:
|
||||
- --strip-components=1
|
||||
notify: Restart zastava-agent
|
||||
|
||||
- name: Make agent binary executable
|
||||
ansible.builtin.file:
|
||||
path: "{{ zastava_install_dir }}/StellaOps.Zastava.Agent"
|
||||
mode: '0755'
|
||||
|
||||
- name: Clean up downloaded archive
|
||||
ansible.builtin.file:
|
||||
path: /tmp/zastava-agent.tar.gz
|
||||
state: absent
|
||||
|
||||
# =========================================================================
|
||||
# Configuration
|
||||
# =========================================================================
|
||||
|
||||
- name: Deploy environment configuration
|
||||
ansible.builtin.template:
|
||||
src: zastava-agent.env.j2
|
||||
dest: "{{ zastava_config_dir }}/zastava-agent.env"
|
||||
owner: root
|
||||
group: "{{ zastava_group }}"
|
||||
mode: '0640'
|
||||
notify: Restart zastava-agent
|
||||
|
||||
# =========================================================================
|
||||
# systemd Service
|
||||
# =========================================================================
|
||||
|
||||
- name: Install systemd service unit
|
||||
ansible.builtin.copy:
|
||||
src: zastava-agent.service
|
||||
dest: /etc/systemd/system/zastava-agent.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart zastava-agent
|
||||
|
||||
- name: Enable and start zastava-agent service
|
||||
ansible.builtin.systemd:
|
||||
name: zastava-agent
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
|
||||
# =========================================================================
|
||||
# Health Verification
|
||||
# =========================================================================
|
||||
|
||||
- name: Wait for agent health endpoint
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ zastava_health_port }}/healthz"
|
||||
method: GET
|
||||
status_code: 200
|
||||
register: health_result
|
||||
retries: 30
|
||||
delay: 2
|
||||
until: health_result.status == 200
|
||||
|
||||
- name: Display agent status
|
||||
ansible.builtin.debug:
|
||||
msg: "Zastava Agent deployed successfully on {{ inventory_hostname }}"
|
||||
|
||||
handlers:
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart zastava-agent
|
||||
ansible.builtin.systemd:
|
||||
name: zastava-agent
|
||||
state: restarted
|
||||
|
||||
# =============================================================================
|
||||
# Post-deployment verification play
|
||||
# =============================================================================
|
||||
- name: Verify Zastava Agent Deployment
|
||||
hosts: zastava_agents
|
||||
become: false
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Check agent readiness
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ zastava_health_port | default(8080) }}/readyz"
|
||||
method: GET
|
||||
return_content: true
|
||||
register: ready_check
|
||||
|
||||
- name: Display deployment summary
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
Zastava Agent Deployment Summary:
|
||||
- Host: {{ inventory_hostname }}
|
||||
- Status: {{ 'Ready' if ready_check.status == 200 else 'Not Ready' }}
|
||||
- Health Endpoint: http://localhost:{{ zastava_health_port | default(8080) }}/healthz
|
||||
- Tenant: {{ zastava_tenant }}
|
||||
- Backend: {{ scanner_backend_url }}
|
||||
Reference in New Issue
Block a user