mirror of
https://github.com/activecm/rita
synced 2026-06-08 13:02:45 +00:00
Simplify installer and update CI (#95)
* simplified installer, removed ansible and remote installs, updated ci * Update ci.yml
This commit is contained in:
+18
-32
@@ -1,61 +1,47 @@
|
||||
name: Build Docker Images
|
||||
name: Build Docker Image
|
||||
|
||||
# on: [pull_request,workflow_dispatch]
|
||||
|
||||
# pull_request: # TODO: delete this line
|
||||
# TODO: comment this back in
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "develop"
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-image:
|
||||
name: "Build Docker Images"
|
||||
name: Build and Push Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
ghcr.io/activecm/rita
|
||||
# generate Docker tags based on the following events/attributes
|
||||
images: ghcr.io/activecm/rita
|
||||
tags: |
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{raw}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
type=sha
|
||||
type=sha
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
# TODO: comment this back in
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
# push: true
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
tags-ignore:
|
||||
- "v*"
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Mod tidy
|
||||
run: |
|
||||
go mod tidy
|
||||
git diff --exit-code
|
||||
|
||||
- name: Verify dependencies
|
||||
run: go mod verify
|
||||
|
||||
- name: Build
|
||||
run: make build
|
||||
|
||||
unit-tests:
|
||||
name: Unit Tests
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
|
||||
- name: Run unit tests
|
||||
run: go test --cover $(go list ./... | grep -v /integration | grep -v /database | grep -v /cmd | grep -v /viewer) -json 2>&1 | tee unit.out && tparse -all --file=unit.out
|
||||
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: unit-test-output
|
||||
path: unit.out
|
||||
|
||||
integration-tests:
|
||||
name: Integration Tests
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
|
||||
- name: Run integration tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./integration/... -json -timeout 1800s 2>&1 | tee integration.out && tparse -all --file=integration.out
|
||||
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: integration-test-output
|
||||
path: integration.out
|
||||
|
||||
database-tests:
|
||||
name: Database Tests
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
|
||||
- name: Run database tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./database/... -json -timeout 1800s 2>&1 | tee database.out && tparse -all --file=database.out
|
||||
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: database-test-output
|
||||
path: database.out
|
||||
|
||||
cmd-tests:
|
||||
name: Cmd Tests
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
|
||||
- name: Run cmd tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./cmd/... -json -timeout 1800s 2>&1 | tee cmd.out && tparse -all --file=cmd.out
|
||||
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: cmd-test-output
|
||||
path: cmd.out
|
||||
|
||||
viewer-tests:
|
||||
name: Viewer Tests
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
|
||||
- name: Run viewer tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./viewer/... -json -timeout 1800s 2>&1 | tee viewer.out && tparse -all --file=viewer.out
|
||||
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: viewer-test-output
|
||||
path: viewer.out
|
||||
@@ -1,37 +1,78 @@
|
||||
name: Generate Installer
|
||||
name: Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
#- unpublished
|
||||
- created
|
||||
- edited
|
||||
#- deleted
|
||||
- prereleased
|
||||
- released
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
workflow_run:
|
||||
workflows: ["Build Docker Images"]
|
||||
branches: [main, develop]
|
||||
types:
|
||||
- completed
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
upload-installer:
|
||||
name: Upload Installer to Release
|
||||
runs-on: ubuntu-22.04
|
||||
ci:
|
||||
name: CI
|
||||
uses: ./.github/workflows/ci.yml
|
||||
|
||||
build-image:
|
||||
name: Build and Push Docker Image
|
||||
needs: ci
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: installer/generate_installer.sh
|
||||
- uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
files: |
|
||||
installer/rita-${{ github.ref_name }}.tar.gz
|
||||
installer/install-rita-zeek-here.sh
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ghcr.io/activecm/rita
|
||||
tags: |
|
||||
type=semver,pattern={{raw}}
|
||||
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
|
||||
generate-installer:
|
||||
name: Generate Installer
|
||||
needs:
|
||||
- ci
|
||||
- build-image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate installer
|
||||
run: installer/generate_installer.sh
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
||||
generate_release_notes: true
|
||||
files: installer/rita-${{ github.ref_name }}.tar.gz
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'develop'
|
||||
|
||||
# Temporarily splitting out tests into separate jobs for improving workflow execution time
|
||||
jobs:
|
||||
unit_test:
|
||||
name: 'Run Unit Tests'
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Install dependencies
|
||||
run: go get .
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
- name: Unit Tests
|
||||
run: go test --cover $(go list ./... | grep -v /integration | grep -v /database | grep -v /cmd | grep -v /viewer ) -json 2>&1 | tee unit.out && tparse -all --file=unit.out
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: media
|
||||
path: unit.out
|
||||
|
||||
integration_test:
|
||||
name: 'Run Integration Tests'
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Install dependencies
|
||||
run: go get .
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
- name: Integration Tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./integration/... -json -timeout 1800s 2>&1 | tee integration.out && tparse -all --file=integration.out
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: media
|
||||
path: integration.out
|
||||
|
||||
database_test:
|
||||
name: 'Run Database Tests'
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Install dependencies
|
||||
run: go get .
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
- name: Database Tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./database/... -json -timeout 1800s 2>&1 | tee database.out && tparse -all --file=database.out
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: media
|
||||
path: database.out
|
||||
cmd_test:
|
||||
name: 'Run Cmd Tests'
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Install dependencies
|
||||
run: go get .
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
- name: Cmd Tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./cmd/... -json -timeout 1800s 2>&1 | tee cmd.out && tparse -all --file=cmd.out
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: media
|
||||
path: cmd.out
|
||||
|
||||
viewer_test:
|
||||
name: 'Run Viewer Tests'
|
||||
runs-on:
|
||||
labels: ubuntu-latest-m
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Install dependencies
|
||||
run: go get .
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Install tparse
|
||||
run: go install github.com/mfridman/tparse@latest
|
||||
- name: Viewer Tests
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: go test ./viewer/... -json -timeout 1800s 2>&1 | tee viewer.out && tparse -all --file=viewer.out
|
||||
- name: Upload test output on failure
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: media
|
||||
path: viewer.out
|
||||
|
||||
|
||||
+2
-3
@@ -43,9 +43,8 @@
|
||||
!/test_data/missing_host/*/*[.log.gz]
|
||||
!/test_data/open_sni/*[.log.gz]
|
||||
|
||||
|
||||
|
||||
|
||||
deployment/threat_intel_feeds/*
|
||||
!deployment/threat_intel_feeds/.gitkeep
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,27 @@ CGO_ENABLED ?= 0
|
||||
GOARCH ?= $(shell go env GOARCH)
|
||||
GOOS ?= $(shell go env GOOS)
|
||||
|
||||
.PHONY: rita
|
||||
rita:
|
||||
CGO_ENABLED=$(CGO_ENABLED) GOARCH=$(GOARCH) GOOS=$(GOOS) go build $(LDFLAGS) -o rita
|
||||
.PHONY: build test test-unit test-integration test-database test-cmd test-viewer clean
|
||||
|
||||
build:
|
||||
CGO_ENABLED=$(CGO_ENABLED) GOARCH=$(GOARCH) GOOS=$(GOOS) go build $(LDFLAGS) -o rita
|
||||
|
||||
test: test-unit test-integration test-database test-cmd test-viewer
|
||||
|
||||
test-unit:
|
||||
go test --cover $$(go list ./... | grep -v /integration | grep -v /database | grep -v /cmd | grep -v /viewer)
|
||||
|
||||
test-integration:
|
||||
go test ./integration/... -timeout 1800s
|
||||
|
||||
test-database:
|
||||
go test ./database/... -timeout 1800s
|
||||
|
||||
test-cmd:
|
||||
go test ./cmd/... -timeout 1800s
|
||||
|
||||
test-viewer:
|
||||
go test ./viewer/... -timeout 1800s
|
||||
|
||||
clean:
|
||||
rm -f rita
|
||||
|
||||
@@ -19,7 +19,7 @@ The framework ingests [Zeek Logs](https://www.zeek.org/) in TSV or JSON format,
|
||||
- **Threat Intel Feed Checking**: Query threat intel feeds to search for suspicious domains and hosts
|
||||
|
||||
## Quick Start
|
||||
Please see our recommended [System Requirements](docs/System%20Requirements.md).
|
||||
Please see our recommended [System Requirements](docs/System%20Requirements.md). RITA requires [Docker Engine](https://docs.docker.com/engine/install/) with the Compose plugin.
|
||||
|
||||
1. Download the [RITA Installer](https://github.com/activecm/rita/releases) for the desired version.
|
||||
|
||||
@@ -27,15 +27,9 @@ The framework ingests [Zeek Logs](https://www.zeek.org/) in TSV or JSON format,
|
||||
```
|
||||
tar -xf rita-<version>-installer.tar.gz
|
||||
```
|
||||
3. Run the install script.
|
||||
3. Run the install script.
|
||||
```
|
||||
./rita-<version>-installer/install_rita.sh <hosts to install on>
|
||||
```
|
||||
To install RITA on the local system, pass `localhost` to the installer.
|
||||
To install RITA on one or more remote systems, pass a comma separated list of IPs or `user@ip` or FQDNs to the installer.
|
||||
For example:
|
||||
```
|
||||
./rita-<version>-installer/install_rita.sh "root@4.4.4.4,8.8.8.8,mydomain.com"
|
||||
./rita-<version>-installer/install_rita.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -51,15 +45,7 @@ The following operating systems/versions and CPU architectures are supported:
|
||||
| Ubuntu | `22.04`, `24.04` | `amd64` |
|
||||
|
||||
## Installing Zeek
|
||||
If you do not already have Zeek installed, it can be installed from [docker-zeek](https://github.com/activecm/docker-zeek).
|
||||
|
||||
```
|
||||
sudo wget -O /usr/local/bin/zeek https://raw.githubusercontent.com/activecm/docker-zeek/master/zeek
|
||||
|
||||
sudo chmod +x /usr/local/bin/zeek
|
||||
|
||||
zeek start
|
||||
```
|
||||
RITA requires [Zeek](https://www.zeek.org/) to generate network logs. If you do not already have Zeek installed, install [docker-zeek](https://github.com/activecm/docker-zeek/releases) and run `zeek start`.
|
||||
|
||||
## Importing
|
||||
Import data into RITA using the `import` command:
|
||||
|
||||
@@ -4,7 +4,7 @@ networks:
|
||||
rita-network: {}
|
||||
services:
|
||||
rita:
|
||||
image: ghcr.io/activecm/rita:latest
|
||||
image: ghcr.io/activecm/rita:${RITA_VERSION:-latest}
|
||||
build: .
|
||||
depends_on:
|
||||
clickhouse:
|
||||
|
||||
@@ -4,6 +4,7 @@ networks:
|
||||
rita-network: {}
|
||||
services:
|
||||
rita:
|
||||
image: ghcr.io/activecm/rita:${RITA_VERSION:-latest}
|
||||
build: .
|
||||
depends_on:
|
||||
clickhouse:
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
## RITA/Zeek Installer
|
||||
|
||||
#### Generated installer directory
|
||||
```
|
||||
rita-<version>.tar.gz
|
||||
│ install_rita.yml
|
||||
│ install_rita.sh
|
||||
| install_zeek.yml
|
||||
| install_pre.yml
|
||||
│
|
||||
└───/scripts
|
||||
│ │ ansible-installer.sh
|
||||
│ │ helper.sh
|
||||
│ │ sshprep.sh
|
||||
│
|
||||
└───/files
|
||||
│ │
|
||||
│ │ rita-<version>-image.tar
|
||||
│ │ docker-compose
|
||||
│ │
|
||||
│ └───/opt
|
||||
│ │ │ docker-compose.yml
|
||||
│ │ │ .env
|
||||
│ │ │ README
|
||||
│ │ │ LICENSE
|
||||
│ │ │ rita.sh
|
||||
| | | zeek
|
||||
│ │
|
||||
│ └───/etc
|
||||
│ │ config.hjson
|
||||
│ │ config.xml
|
||||
│ │ http_extensions_list.csv
|
||||
│ │ logger-cron
|
||||
│ │ syslog-ng.conf
|
||||
│ │ timezone.xml
|
||||
│ └───/threat_intel_feeds
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Generating an installer
|
||||
|
||||
Note: generating the installer on a branch that has no tag when running `git describe --always --abbrev=0 --tags` will generate a broken installer.
|
||||
|
||||
Run:
|
||||
`./installer/generate_installer.sh`
|
||||
|
||||
The script will generate an installer tar file in the `installer` folder, named `rita-v<version number>-installer.tar.gz`.
|
||||
|
||||
Verify that all files in the above directory tree exist in the generated tar file.
|
||||
|
||||
Verify that all occurences of "REPLACE_ME" within scripts and/or playbooks got updated with the proper version number that is expected.
|
||||
The version for RITA that gets replaced should match the current tag.
|
||||
|
||||
The version for Zeek that gets replaced should be the desired version of docker-zeek to be used in this release.
|
||||
|
||||
The docker-zeek repo pushes a built multi-architecture image of zeek to DockerHub using Github Actions. The generate_installer script should specify which tag version on [Dockerhub](https://hub.docker.com/r/activecm/zeek/tags) you wish to include with this release. Multi-architecture tags require all architectures to finish building before being merged into one tag, so if the build actions are in progress, please be patient and wait for them to finish before attempting to install it.
|
||||
|
||||
### Running the installer
|
||||
To install RITA on the current system, run:
|
||||
`./rita-v<version>-installer/install_rita.sh localhost`.
|
||||
|
||||
To install RITA on a remote system, run:
|
||||
`./rita-v<version>-installer/install_rita.sh root@8.8.8.8`.
|
||||
|
||||
### Updating the installer
|
||||
Each file that is expected to be in the installer must be explicitly copied to the installer within the `./installer/generate_installer.sh` script.
|
||||
|
||||
If any new Ansible playbook or script that uses the "REPLACE_ME" string to insert a version is added, the generate_installer script must be updated to replace that string with the proper version.
|
||||
|
||||
Any versions for RITA should NOT be hard-coded. The version should be retrieved by the generate_installer script automatically. The only hard-coded versions in the generator should be for external projects.
|
||||
|
||||
|
||||
### "One-line installer"
|
||||
To make installing both RITA and Zeek easier, a one-line installer is created and uploaded to the release artifacts on Github. This installer is generated with the generate_installer.sh script as well, but is uploaded to the release within the Generate Installer Github Action.
|
||||
This one line installer is a single script (not a tar file). It installs RITA & Zeek on the local system and does NOT require passing any arguments to it.
|
||||
|
||||
|
||||
### Zeek
|
||||
There are multiple moving parts in order to build Zeek and include it in a RITA install bundle.
|
||||
|
||||
The main Zeek repo is [docker-zeek](https://github.com/activecm/docker-zeek). This repository contains the Dockerfile definition needed to build the docker image of Zeek that includes custom modifications like timeouts and the [zeek-open-connections](https://github.com/activecm/zeek-open-connections) plugin.
|
||||
|
||||
The docker-zeek repo is responsible for building the multi-arch image for Zeek in Github Actions. The actions automatically upload the image to Dockerhub. In order to test changes locally without uploading them to Dockerhub, the docker-zeek image must be built on your local system and tagged with a name that is NOT similar to `activecm/zeek:<any version>`. To test the zeek script with this custom-built image, the `zeek` script in the docker-zeek repo must be updated to use your custom tag instead of whatever is listed in the `IMAGE_NAME` variable.
|
||||
|
||||
The zeek-open-connections plugin must have an updated tag in order to be recognized by the Zeek package manager (zkg). Follow the instructions in that repo's README for more details.
|
||||
|
||||
The RITA installer includes an Ansible playbook that pulls the desired version of `activecm/zeek` from Dockerhub and creates the necessary directories needed to run Zeek. The installer generator also pulls the `zeek` script from the `docker-zeek` repo and includes it in the installer, along with listing the proper image version in the `IMAGE_NAME` variable. Aside from these two items, Zeek and RITA are independent of each other.
|
||||
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# creates a dev installer with locally built Docker images
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RITA_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# load helper functions
|
||||
HELPER_FILE="$SCRIPT_DIR/helper.sh"
|
||||
[[ -f "$HELPER_FILE" ]] || { echo "Helper functions script not found: $HELPER_FILE" >&2; exit 1; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$HELPER_FILE"
|
||||
|
||||
status "Creating RITA dev installer..."
|
||||
|
||||
ARM=false
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--arm)
|
||||
ARM=true
|
||||
shift
|
||||
;;
|
||||
-*|--*)
|
||||
echo "Unknown option $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# -------------------------
|
||||
# create base installer
|
||||
# -------------------------
|
||||
"$SCRIPT_DIR/generate_installer.sh"
|
||||
|
||||
# -------------------------
|
||||
# determine docker command
|
||||
# -------------------------
|
||||
if docker info >/dev/null 2>&1; then
|
||||
DOCKER_CMD=(docker)
|
||||
else
|
||||
DOCKER_CMD=(sudo docker)
|
||||
fi
|
||||
|
||||
# -------------------------
|
||||
# determine version
|
||||
# -------------------------
|
||||
if VERSION="$(git -C "$RITA_DIR" describe --tags --exact-match 2>/dev/null)"; then
|
||||
:
|
||||
elif VERSION="$(git -C "$RITA_DIR" describe --tags --dirty --always 2>/dev/null)"; then
|
||||
:
|
||||
else
|
||||
fail "Unable to determine RITA version."
|
||||
fi
|
||||
[[ -n "$VERSION" ]] || fail "VERSION not set"
|
||||
|
||||
# paths
|
||||
TARBALL="${SCRIPT_DIR}/rita-${VERSION}.tar.gz"
|
||||
INSTALLER_DIR="${SCRIPT_DIR}/rita-${VERSION}-installer"
|
||||
ENV_FILE="${INSTALLER_DIR}/files/opt/.env"
|
||||
COMPOSE_FILE="${RITA_DIR}/docker-compose.yml"
|
||||
|
||||
# -------------------------
|
||||
# unpack installer tarball
|
||||
# -------------------------
|
||||
require_file "$TARBALL"
|
||||
tar -xzf "$TARBALL" -C "$SCRIPT_DIR"
|
||||
|
||||
# parse clickhouse version from .env
|
||||
require_file "$ENV_FILE"
|
||||
CLICKHOUSE_VERSION="$(awk -F= '$1=="CLICKHOUSE_VERSION"{v=$2} END{gsub(/^[[:space:]]+|[[:space:]]+$/,"",v); gsub(/^"|"$|^\047|\047$/,"",v); print v}' "$ENV_FILE")"
|
||||
[[ -n "${CLICKHOUSE_VERSION:-}" ]] || fail "CLICKHOUSE_VERSION is missing from $ENV_FILE"
|
||||
status "Using CLICKHOUSE_VERSION=$CLICKHOUSE_VERSION"
|
||||
|
||||
# determine target platform
|
||||
PLATFORM="linux/amd64"
|
||||
if [ "${ARM}" = "true" ]; then
|
||||
PLATFORM="linux/arm64/v8"
|
||||
fi
|
||||
|
||||
# verify docker is available
|
||||
"${DOCKER_CMD[@]}" version >/dev/null 2>&1 || fail "docker is required and must be runnable"
|
||||
|
||||
# verify gzip is available
|
||||
command -v gzip >/dev/null 2>&1 || fail "gzip is required"
|
||||
|
||||
# -------------------------
|
||||
# build rita image
|
||||
# -------------------------
|
||||
status "Building RITA image for ${PLATFORM}..."
|
||||
export DOCKER_BUILDKIT=1
|
||||
export RITA_VERSION="${VERSION}"
|
||||
if [ "${DOCKER_CMD[0]}" = "sudo" ]; then
|
||||
sudo env DOCKER_DEFAULT_PLATFORM="$PLATFORM" BUILDX_NO_DEFAULT_ATTESTATIONS=1 docker compose --project-directory "$RITA_DIR" -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build rita
|
||||
else
|
||||
DOCKER_DEFAULT_PLATFORM="$PLATFORM" BUILDX_NO_DEFAULT_ATTESTATIONS=1 docker compose --project-directory "$RITA_DIR" -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build rita
|
||||
fi
|
||||
|
||||
# -------------------------
|
||||
# save images to disk
|
||||
# -------------------------
|
||||
INSTALL_OPT="${INSTALLER_DIR}/files/opt"
|
||||
require_dir "$INSTALL_OPT"
|
||||
|
||||
RITA_IMAGE="ghcr.io/activecm/rita:${VERSION}"
|
||||
|
||||
# docker save --platform requires Docker 26+
|
||||
status "Saving RITA image..."
|
||||
"${DOCKER_CMD[@]}" save --platform "$PLATFORM" "$RITA_IMAGE" | gzip -c > "$INSTALL_OPT/rita-${VERSION}-image.tar.gz"
|
||||
|
||||
save_pulled_image() {
|
||||
local name="$1" ref="$2" outfile="$3"
|
||||
status "Saving ${name} image..."
|
||||
"${DOCKER_CMD[@]}" pull --platform "$PLATFORM" "$ref"
|
||||
"${DOCKER_CMD[@]}" save --platform "$PLATFORM" "$ref" | gzip -c > "$outfile"
|
||||
}
|
||||
|
||||
save_pulled_image "syslog-ng" "lscr.io/linuxserver/syslog-ng:latest" "$INSTALL_OPT/syslog-ng-latest.tar.gz"
|
||||
save_pulled_image "ClickHouse" "clickhouse/clickhouse-server:${CLICKHOUSE_VERSION}" "$INSTALL_OPT/clickhouse-${CLICKHOUSE_VERSION}.tar.gz"
|
||||
|
||||
# sanity checks
|
||||
require_nonempty_file "$INSTALL_OPT/rita-${VERSION}-image.tar.gz"
|
||||
require_nonempty_file "$INSTALL_OPT/syslog-ng-latest.tar.gz"
|
||||
require_nonempty_file "$INSTALL_OPT/clickhouse-${CLICKHOUSE_VERSION}.tar.gz"
|
||||
|
||||
# -------------------------
|
||||
# repack tarball
|
||||
# -------------------------
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
tar --no-xattrs --disable-copyfile -czf "$TARBALL" -C "$SCRIPT_DIR" "$(basename "$INSTALLER_DIR")"
|
||||
else
|
||||
tar -czf "$TARBALL" -C "$SCRIPT_DIR" "$(basename "$INSTALLER_DIR")"
|
||||
fi
|
||||
|
||||
# clean up
|
||||
remove_dir "$INSTALLER_DIR"
|
||||
|
||||
status "Dev installer created: $(basename "$TARBALL")"
|
||||
status "Platform: ${PLATFORM}"
|
||||
@@ -1,22 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# This script generates the RITA installer by creating a temporary folder in the current directory named 'stage'
|
||||
# and copies files that must be in the installer into the stage folder.
|
||||
# Once all directories are placed in stage, it is compressed and stage is deleted.
|
||||
|
||||
ZEEK_VERSION=6.2.1
|
||||
# this script generates the RITA installer
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RITA_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# load helper functions
|
||||
HELPER_FILE="$SCRIPT_DIR/install_scripts/helper.sh"
|
||||
HELPER_FILE="$SCRIPT_DIR/helper.sh"
|
||||
[[ -f "$HELPER_FILE" ]] || { echo "Helper functions script not found: $HELPER_FILE" >&2; exit 1; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$HELPER_FILE"
|
||||
|
||||
|
||||
# get RITA version from git
|
||||
if VERSION="$(git -C "$RITA_DIR" describe --tags --exact-match 2>/dev/null)"; then
|
||||
: # release / ci
|
||||
@@ -29,9 +24,6 @@ fi
|
||||
|
||||
status "Generating installer for RITA $VERSION..."
|
||||
|
||||
# change working directory to directory of this script
|
||||
# pushd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" > /dev/null
|
||||
|
||||
# create staging directory
|
||||
INSTALLER_DIR="${SCRIPT_DIR}/rita-$VERSION-installer"
|
||||
OUTPUT_TARBALL="${SCRIPT_DIR}/rita-$VERSION.tar.gz"
|
||||
@@ -39,74 +31,50 @@ remove_dir "$INSTALLER_DIR"
|
||||
remove_file "$OUTPUT_TARBALL"
|
||||
create_new_dir "$INSTALLER_DIR"
|
||||
|
||||
# create ansible subfolders
|
||||
# create subfolders
|
||||
SCRIPTS="$INSTALLER_DIR/scripts"
|
||||
ANSIBLE_FILES="$INSTALLER_DIR/files"
|
||||
FILES="$INSTALLER_DIR/files"
|
||||
create_new_dir "$SCRIPTS"
|
||||
create_new_dir "$ANSIBLE_FILES"
|
||||
create_new_dir "$FILES"
|
||||
|
||||
# create subfolders (for files that installed RITA will contain)
|
||||
INSTALL_OPT="$ANSIBLE_FILES"/opt
|
||||
INSTALL_ETC="$ANSIBLE_FILES"/etc
|
||||
INSTALL_OPT="$FILES/opt"
|
||||
INSTALL_ETC="$FILES/etc"
|
||||
create_new_dir "$INSTALL_OPT"
|
||||
create_new_dir "$INSTALL_ETC"
|
||||
|
||||
# copy files in base dir
|
||||
copy_file "${SCRIPT_DIR}/install-rita-zeek-here.sh" "$INSTALLER_DIR"
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/install_zeek.yml" "$INSTALLER_DIR"
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/install_rita.yml" "$INSTALLER_DIR"
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/install_pre.yml" "$INSTALLER_DIR"
|
||||
# copy entrypoint
|
||||
copy_file "${SCRIPT_DIR}/install_rita.sh" "$INSTALLER_DIR"
|
||||
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/install_rita.sh" "$INSTALLER_DIR" # entrypoint
|
||||
# copy helper scripts
|
||||
copy_file "${SCRIPT_DIR}/helper.sh" "$SCRIPTS"
|
||||
|
||||
# copy files to helper script folder
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/ansible-installer.sh" "$SCRIPTS"
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/helper.sh" "$SCRIPTS"
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/sshprep.sh" "$SCRIPTS"
|
||||
|
||||
# copy files to the ansible files folder
|
||||
copy_file "${SCRIPT_DIR}/install_scripts/docker-compose" "$ANSIBLE_FILES" # docker-compose v1 backwards compatibility script
|
||||
|
||||
# copy over configuration files to /files/etc
|
||||
# copy configuration files to /files/etc
|
||||
copy_dir_contents "${RITA_DIR}/deployment" "$INSTALL_ETC"
|
||||
rm -f "$INSTALL_ETC/threat_intel_feeds/.gitkeep"
|
||||
copy_file "${RITA_DIR}/default_config.hjson" "$INSTALL_ETC/config.hjson"
|
||||
|
||||
# copy over installed files to /opt
|
||||
# copy installed files to /files/opt
|
||||
copy_file "${RITA_DIR}/rita.sh" "$INSTALL_OPT"
|
||||
curl --fail --silent --show-error -o "${INSTALL_OPT}/zeek" https://raw.githubusercontent.com/activecm/docker-zeek/master/zeek
|
||||
chmod +x "${INSTALL_OPT}/zeek"
|
||||
curl --fail --silent --show-error -o "${INSTALL_OPT}/zeek_log_transport.sh" https://raw.githubusercontent.com/activecm/zeek-log-transport/refs/heads/master/zeek_log_transport.sh
|
||||
chmod +x "${INSTALL_OPT}/zeek_log_transport.sh"
|
||||
copy_file "${RITA_DIR}/.env.production" "${INSTALL_OPT}/.env"
|
||||
copy_file "${RITA_DIR}/docker-compose.prod.yml" "${INSTALL_OPT}/docker-compose.yml"
|
||||
copy_file "${RITA_DIR}/LICENSE" "${INSTALL_OPT}/LICENSE"
|
||||
copy_file "${RITA_DIR}/README.md" "${INSTALL_OPT}/README"
|
||||
|
||||
# update version variables for files that need them
|
||||
# update version variables
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
sed -i'.bak' "s/RITA_REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install-rita-zeek-here.sh"
|
||||
sed -i'.bak' "s/REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install_rita.yml"
|
||||
sed -i'.bak' "s/REPLACE_ME/${ZEEK_VERSION}/g" "${INSTALLER_DIR}/install_zeek.yml"
|
||||
sed -i'.bak' "s/REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install_rita.sh"
|
||||
sed -i'.bak' "s#ghcr.io/activecm/rita:latest#ghcr.io/activecm/rita:${VERSION}#g" "${INSTALL_OPT}/docker-compose.yml"
|
||||
|
||||
remove_file "${INSTALLER_DIR}/install-rita-zeek-here.sh.bak"
|
||||
remove_file "${INSTALLER_DIR}/install_rita.yml.bak"
|
||||
remove_file "${INSTALLER_DIR}/install_zeek.yml.bak"
|
||||
remove_file "${INSTALLER_DIR}/install_rita.sh.bak"
|
||||
remove_file "${INSTALL_OPT}/docker-compose.yml.bak"
|
||||
else
|
||||
sed -i "s/RITA_REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install-rita-zeek-here.sh"
|
||||
sed -i "s/REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install_rita.yml"
|
||||
sed -i "s/REPLACE_ME/${ZEEK_VERSION}/g" "${INSTALLER_DIR}/install_zeek.yml"
|
||||
sed -i "s/REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install_rita.sh"
|
||||
sed -i "s#ghcr.io/activecm/rita:latest#ghcr.io/activecm/rita:${VERSION}#g" "${INSTALL_OPT}/docker-compose.yml"
|
||||
else
|
||||
sed -i "s/REPLACE_ME/${VERSION}/g" "${INSTALLER_DIR}/install_rita.sh"
|
||||
fi
|
||||
|
||||
# create tarball from staging folder
|
||||
# write RITA_VERSION into the env file so docker compose resolves the image tag
|
||||
printf 'RITA_VERSION=%s\n' "${VERSION}" >> "${INSTALL_OPT}/.env"
|
||||
|
||||
# create tarball
|
||||
tar -czf "$OUTPUT_TARBALL" -C "$SCRIPT_DIR" "$(basename "$INSTALLER_DIR")"
|
||||
|
||||
# delete staging folder
|
||||
# clean up staging directory
|
||||
remove_dir "$INSTALLER_DIR"
|
||||
|
||||
status "Finished generating installer."
|
||||
status "Finished generating installer: $(basename "$OUTPUT_TARBALL")"
|
||||
|
||||
@@ -8,8 +8,6 @@ fi
|
||||
|
||||
RED=""
|
||||
YELLOW=""
|
||||
BLUE=""
|
||||
GREEN=""
|
||||
NORMAL=""
|
||||
|
||||
# SUDO and SUDO_E are intentionally initialized to empty here.
|
||||
@@ -25,44 +23,56 @@ verbose="yes"
|
||||
|
||||
# use colors if terminal supports it
|
||||
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
|
||||
RED=$(tput setaf 1)
|
||||
YELLOW=$(tput setaf 3)
|
||||
BLUE=$(tput setaf 4)
|
||||
GREEN=$(tput setaf 2)
|
||||
NORMAL=$(tput sgr0)
|
||||
RED=$(tput setaf 1)
|
||||
YELLOW=$(tput setaf 3)
|
||||
NORMAL=$(tput sgr0)
|
||||
fi
|
||||
|
||||
# something failed, exit
|
||||
fail() {
|
||||
echo "${RED}$*, exiting.${NORMAL}" >&2
|
||||
exit 1
|
||||
echo "${RED}$*, exiting.${NORMAL}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# print status message if verbose is enabled
|
||||
status() {
|
||||
if [[ "${verbose:-}" == "yes" ]]; then
|
||||
echo "== $*" >&2
|
||||
fi
|
||||
if [[ "${verbose:-}" == "yes" ]]; then
|
||||
echo "== $*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# ensure script is run with sudo privileges
|
||||
# ensure script is run with sudo privileges
|
||||
require_sudo() {
|
||||
# check if running as root
|
||||
if [[ "$EUID" -eq 0 ]]; then
|
||||
if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
|
||||
SUDO=""
|
||||
SUDO_E=""
|
||||
export SUDO SUDO_E
|
||||
return 0
|
||||
fi
|
||||
|
||||
# check that we are able to run commands with sudo (non-interactive)
|
||||
if sudo -v </dev/null 2>/dev/null; then
|
||||
# sudo must exist
|
||||
require_cmd "sudo"
|
||||
|
||||
# check for passwordless sudo
|
||||
if sudo -n true >/dev/null 2>&1; then
|
||||
SUDO="sudo"
|
||||
SUDO_E="sudo -E"
|
||||
export SUDO SUDO_E
|
||||
return 0
|
||||
fi
|
||||
|
||||
# check for password-required sudo if in an interactive shell
|
||||
if [[ -t 0 ]]; then
|
||||
status "Administrator privileges required. You may be prompted for your sudo password."
|
||||
if sudo -v; then
|
||||
SUDO="sudo"
|
||||
SUDO_E="sudo -E"
|
||||
export SUDO SUDO_E
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
fail "Missing administrator privileges. Please run with an account that has sudo privileges."
|
||||
}
|
||||
|
||||
@@ -73,17 +83,17 @@ require_cmd() {
|
||||
|
||||
# require that a file exists
|
||||
require_file() {
|
||||
[[ -f "$1" ]] || { fail "Required file not found: $1"; }
|
||||
[[ -f "$1" ]] || fail "Required file not found: $1"
|
||||
}
|
||||
|
||||
# require that a file exists and is not empty
|
||||
require_nonempty_file() {
|
||||
[[ -s "$1" ]] || fail "Required file missing or empty: $1"
|
||||
}
|
||||
|
||||
# require that a directory exists
|
||||
require_dir() {
|
||||
[[ -d "$1" ]] || { fail "Required directory not found: $1"; }
|
||||
}
|
||||
|
||||
# require that an environment variable is set and non-empty
|
||||
require_env() {
|
||||
[[ -n "${!1:-}" ]] || fail "Required environment variable not set or empty: $1"
|
||||
[[ -d "$1" ]] || fail "Required directory not found: $1"
|
||||
}
|
||||
|
||||
# copy a file, ensuring the source exists and the destination parent directory exists
|
||||
@@ -93,33 +103,27 @@ copy_file() {
|
||||
|
||||
require_file "$src"
|
||||
|
||||
# if user provided a directory as destination, copy into that directory
|
||||
if [[ -d "$dst" ]]; then
|
||||
cp -- "$src" "$dst" || fail "Failed to copy file from $src to $dst"
|
||||
require_file "$dst/$(basename "$src")"
|
||||
else
|
||||
# if user provided a full destination path (including filename), ensure parent directory exists
|
||||
require_dir "$(dirname "$dst")"
|
||||
cp -- "$src" "$dst" || fail "Failed to copy file from $src to $dst"
|
||||
require_file "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# copy a directory recursively, ensuring the source exists and the destination parent directory exists
|
||||
copy_dir() {
|
||||
require_dir "$1"
|
||||
require_dir "$2"
|
||||
cp -r -- "$1" "$2" || fail "Failed to copy directory from $1 to $2"
|
||||
}
|
||||
|
||||
# this version does not copy the dir itself, nor any dotfiles inside it
|
||||
# copy the contents of a directory (not the directory itself or dotfiles)
|
||||
copy_dir_contents() {
|
||||
require_nonempty_dir "$1"
|
||||
require_dir "$1"
|
||||
if ! find "$1" -mindepth 1 -maxdepth 1 ! -name '.*' -print -quit | grep -q .; then
|
||||
fail "Directory is empty: $1"
|
||||
fi
|
||||
require_dir "$2"
|
||||
cp -r -- "$1"/* "$2" || fail "Failed to copy contents from $1 to $2"
|
||||
}
|
||||
|
||||
# create a new directory, failing if it already exists
|
||||
create_new_dir() {
|
||||
if [[ -e "$1" ]]; then
|
||||
fail "Failed to create new directory, path already exists: $1"
|
||||
@@ -128,62 +132,19 @@ create_new_dir() {
|
||||
require_dir "$1"
|
||||
}
|
||||
|
||||
# check if a directory exists and is empty
|
||||
dir_is_empty() {
|
||||
[[ -d "$1" ]] || return 1
|
||||
[[ -z "$(ls -A "$1" 2>/dev/null)" ]]
|
||||
}
|
||||
|
||||
# ensure a directory exists; create it if missing
|
||||
ensure_dir() {
|
||||
[[ -d "$1" ]] && return 0
|
||||
create_new_dir "$1"
|
||||
}
|
||||
|
||||
# ensure a directory exists (create if not) and is empty
|
||||
ensure_empty_dir() {
|
||||
ensure_dir "$1"
|
||||
if ! dir_is_empty "$1"; then
|
||||
clear_dir "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# require that a directory has at least one non-dot entry (file or dir)
|
||||
require_nonempty_dir() {
|
||||
require_dir "$1"
|
||||
if ! find "$1" -mindepth 1 -maxdepth 1 ! -name '.*' -print -quit | grep -q .; then
|
||||
fail "Directory is empty: $1"
|
||||
fi
|
||||
}
|
||||
|
||||
# remove a file (or symlink) if it exists
|
||||
remove_file() {
|
||||
local path="$1"
|
||||
if [[ -e "$path" || -L "$path" ]]; then
|
||||
rm -f -- "$path" || fail "Failed to remove file: $path"
|
||||
rm -f -- "$path" || fail "Failed to remove file: $path"
|
||||
fi
|
||||
}
|
||||
|
||||
# remove a directory if it exists
|
||||
remove_dir() {
|
||||
if [[ -d "$1" ]]; then
|
||||
rm -rf -- "$1" || fail "Failed to remove directory: $1"
|
||||
rm -rf -- "$1" || fail "Failed to remove directory: $1"
|
||||
elif [[ -e "$1" || -L "$1" ]]; then
|
||||
fail "Expected directory but found non-directory: $1"
|
||||
fi
|
||||
}
|
||||
|
||||
# delete everything inside a directory, but keep the directory itself
|
||||
clear_dir() {
|
||||
[[ -n "${1:-}" ]] || fail "clear_dir: missing dir"
|
||||
local dir="$1"
|
||||
|
||||
if [[ -e "$dir" || -L "$dir" ]]; then
|
||||
[[ -d "$dir" ]] || fail "Expected directory but found non-directory: $dir"
|
||||
else
|
||||
ensure_dir "$dir"
|
||||
fi
|
||||
|
||||
# Delete contents (including dotfiles) but not the directory itself.
|
||||
find -- "$dir" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + || fail "Failed to clear directory: $dir"
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# This script downloads and installs rita, zeek, and all dependencies on the current system
|
||||
|
||||
export RITA_VERSION="RITA_REPLACE_ME"
|
||||
export zeek_release='latest'
|
||||
export PATH="$PATH:/usr/local/bin/"
|
||||
echo 'export PATH=$PATH:/usr/local/bin/' | sudo tee -a /etc/profile.d/localpath.sh
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
SUDO="/usr/bin/sudo "
|
||||
fi
|
||||
|
||||
$SUDO mkdir -p /usr/local/bin/
|
||||
|
||||
echo "==== Installing rita $RITA_VERSION ====" >&2
|
||||
cd
|
||||
wget https://github.com/activecm/rita/releases/download/${RITA_VERSION}/rita-${RITA_VERSION}.tar.gz
|
||||
tar -xzvf rita-${RITA_VERSION}.tar.gz
|
||||
cd rita-${RITA_VERSION}-installer
|
||||
./install_rita.sh localhost </dev/stderr
|
||||
rita help </dev/stderr
|
||||
|
||||
echo "==== Installing zeek $zeek_release ====" >&2
|
||||
$SUDO wget -O /usr/local/bin/zeek https://raw.githubusercontent.com/activecm/docker-zeek/master/zeek
|
||||
$SUDO chmod +x /usr/local/bin/zeek
|
||||
/usr/local/bin/zeek pull </dev/stderr
|
||||
sleep 2
|
||||
/usr/local/bin/zeek stop </dev/stderr
|
||||
echo "Please run 'zeek start' if you want to start zeek running in the background." >&2
|
||||
echo 'If your system has trouble locating either zeek or rita we recommend logging out and logging back in.' >&2
|
||||
Executable
+226
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# RITA installer script
|
||||
# this installer must be run directly on the system where RITA will be installed
|
||||
|
||||
# -------------------------
|
||||
# constants
|
||||
# -------------------------
|
||||
RITA_VERSION="REPLACE_ME"
|
||||
|
||||
# -------------------------
|
||||
# paths inside installer
|
||||
# -------------------------
|
||||
INSTALLER="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SRC_FILES="${INSTALLER}/files"
|
||||
SRC_OPT="${SRC_FILES}/opt"
|
||||
SRC_ETC="${SRC_FILES}/etc"
|
||||
|
||||
# -------------------------
|
||||
# paths on target system
|
||||
# -------------------------
|
||||
ETC="/etc/rita"
|
||||
OPT="/opt/rita"
|
||||
|
||||
# -------------------------
|
||||
# load helper functions
|
||||
# -------------------------
|
||||
HELPER_FILE="${INSTALLER}/scripts/helper.sh"
|
||||
[[ -f "$HELPER_FILE" ]] || { echo "Helper functions script not found: $HELPER_FILE" >&2; exit 1; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$HELPER_FILE"
|
||||
|
||||
# ensure /usr/local/bin is in PATH
|
||||
export PATH="/usr/local/bin:${PATH}"
|
||||
|
||||
# -------------------------
|
||||
# local functions
|
||||
# -------------------------
|
||||
show_help() {
|
||||
cat >&2 <<EOF
|
||||
|
||||
Usage: $(basename "$0") [options]
|
||||
|
||||
This installer installs RITA on the local system.
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message and exit
|
||||
|
||||
Example:
|
||||
$(basename "$0")
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
require_docker_ready() {
|
||||
command -v docker >/dev/null 2>&1 || fail "Docker is required. Install Docker Engine + the compose plugin, then re-run."
|
||||
|
||||
"${DSUDO[@]}" docker info >/dev/null 2>&1 || fail "Docker daemon is not reachable. Ensure docker is running (systemctl enable --now docker)."
|
||||
|
||||
if command -v docker-compose >/dev/null 2>&1 && ! "${DSUDO[@]}" docker compose version >/dev/null 2>&1; then
|
||||
fail "'docker-compose' (v1) is installed, but RITA requires Docker Compose v2 ('docker compose')."
|
||||
fi
|
||||
|
||||
"${DSUDO[@]}" docker compose version >/dev/null 2>&1 || fail "Docker Compose v2 is required (the 'docker compose' plugin). Install Docker Compose v2, then re-run."
|
||||
}
|
||||
|
||||
# -------------------------
|
||||
# early help check
|
||||
# -------------------------
|
||||
if [[ ${1:-} == "-h" || ${1:-} == "--help" ]]; then
|
||||
show_help
|
||||
fi
|
||||
|
||||
# --------------------------
|
||||
# requirements checks
|
||||
# --------------------------
|
||||
status "Verifying system requirements..."
|
||||
|
||||
# sudo checks and setup
|
||||
require_sudo
|
||||
|
||||
# special-case sudo for docker commands
|
||||
DSUDO=()
|
||||
if [[ "$(uname)" != "Darwin" && -n "${SUDO:-}" ]]; then
|
||||
DSUDO=("$SUDO")
|
||||
fi
|
||||
|
||||
# docker checks
|
||||
require_docker_ready
|
||||
|
||||
# command checks
|
||||
require_cmd install
|
||||
require_cmd cp
|
||||
|
||||
# --------------------------
|
||||
# begin installation
|
||||
# --------------------------
|
||||
status "Installing RITA..."
|
||||
|
||||
# verify required source directories exist
|
||||
require_dir "$SRC_FILES"
|
||||
require_dir "$SRC_OPT"
|
||||
require_dir "$SRC_ETC"
|
||||
|
||||
# -------------------------
|
||||
# stop running old system
|
||||
# -------------------------
|
||||
status "Checking for existing RITA installation..."
|
||||
if command -v rita >/dev/null 2>&1; then
|
||||
status "Stopping existing RITA..."
|
||||
"${DSUDO[@]}" rita down >/dev/null 2>&1 || true
|
||||
elif [[ -x /usr/local/bin/rita ]]; then
|
||||
status "Stopping existing RITA..."
|
||||
"${DSUDO[@]}" /usr/local/bin/rita down >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# ---------------------------
|
||||
# create required directories
|
||||
# ---------------------------
|
||||
status "Creating directories..."
|
||||
"${DSUDO[@]}" mkdir -p "$ETC" "$OPT"
|
||||
"${DSUDO[@]}" chmod 0755 "$ETC" "$OPT"
|
||||
|
||||
# -------------------------
|
||||
# install rita command
|
||||
# -------------------------
|
||||
status "Installing rita..."
|
||||
require_file "${SRC_OPT}/rita.sh"
|
||||
RITA_BIN="/usr/local/bin/rita"
|
||||
"${DSUDO[@]}" install -m 0755 "${SRC_OPT}/rita.sh" "$RITA_BIN"
|
||||
command -v "$RITA_BIN" >/dev/null 2>&1 || fail "rita was not installed correctly to ${RITA_BIN}"
|
||||
|
||||
# -------------------------
|
||||
# copy opt
|
||||
# -------------------------
|
||||
"${DSUDO[@]}" cp -a "${SRC_OPT}/." "${OPT}/"
|
||||
|
||||
# --------------------------------------------
|
||||
# copy etc and preserve existing config.hjson
|
||||
# --------------------------------------------
|
||||
CFG_DST="${ETC}/config.hjson"
|
||||
CFG_BACKUP=""
|
||||
|
||||
cleanup_cfg_backup() {
|
||||
if [[ -n "${CFG_BACKUP:-}" && -f "${CFG_BACKUP:-}" ]]; then
|
||||
"${DSUDO[@]}" rm -f "$CFG_BACKUP" || true
|
||||
fi
|
||||
}
|
||||
trap cleanup_cfg_backup EXIT
|
||||
|
||||
if [[ -f "$CFG_DST" ]]; then
|
||||
status "Preserving existing config.hjson..."
|
||||
CFG_BACKUP="$(mktemp /tmp/rita_config.hjson.XXXXXX)"
|
||||
"${DSUDO[@]}" cp -f "$CFG_DST" "$CFG_BACKUP"
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
"${DSUDO[@]}" chown root:wheel "$CFG_BACKUP" || true
|
||||
else
|
||||
"${DSUDO[@]}" chown root:root "$CFG_BACKUP" || true
|
||||
fi
|
||||
"${DSUDO[@]}" chmod 0644 "$CFG_BACKUP" || true
|
||||
fi
|
||||
|
||||
"${DSUDO[@]}" cp -a "${SRC_ETC}/." "${ETC}/"
|
||||
|
||||
if [[ -n "$CFG_BACKUP" && -f "$CFG_BACKUP" ]]; then
|
||||
status "Restoring preserved config.hjson..."
|
||||
"${DSUDO[@]}" cp -f "$CFG_BACKUP" "$CFG_DST"
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
"${DSUDO[@]}" chown root:wheel "$CFG_DST" || true
|
||||
else
|
||||
"${DSUDO[@]}" chown root:root "$CFG_DST" || true
|
||||
fi
|
||||
"${DSUDO[@]}" chmod 0644 "$CFG_DST" || true
|
||||
"${DSUDO[@]}" rm -f "$CFG_BACKUP" || true
|
||||
CFG_BACKUP=""
|
||||
fi
|
||||
|
||||
trap - EXIT
|
||||
|
||||
# -------------------------
|
||||
# load installer env
|
||||
# -------------------------
|
||||
ENV="${OPT}/.env"
|
||||
require_file "$ENV"
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$ENV"
|
||||
set +a
|
||||
|
||||
# -------------------------
|
||||
# pull rita docker image
|
||||
# -------------------------
|
||||
status "Pulling RITA docker image..."
|
||||
RITA_IMAGE="ghcr.io/activecm/rita:${RITA_VERSION}"
|
||||
load_image() {
|
||||
local name="$1" pull_ref="$2" tar_path="$3"
|
||||
status "Loading ${name} image..."
|
||||
if [[ -f "$tar_path" ]]; then
|
||||
"${DSUDO[@]}" docker load -i "$tar_path"
|
||||
elif "${DSUDO[@]}" docker pull "$pull_ref"; then
|
||||
:
|
||||
else
|
||||
fail "Unable to load ${name} image. No local image at ${tar_path} and pull failed."
|
||||
fi
|
||||
}
|
||||
|
||||
load_image "RITA" "$RITA_IMAGE" "${OPT}/rita-${RITA_VERSION}-image.tar.gz"
|
||||
load_image "syslog-ng" "lscr.io/linuxserver/syslog-ng:latest" "${OPT}/syslog-ng-latest.tar.gz"
|
||||
load_image "ClickHouse" "clickhouse/clickhouse-server:${CLICKHOUSE_VERSION}" "${OPT}/clickhouse-${CLICKHOUSE_VERSION}.tar.gz"
|
||||
|
||||
|
||||
echo \
|
||||
"
|
||||
░█▀▀█ ▀█▀ ▀▀█▀▀ ─█▀▀█
|
||||
░█▄▄▀ ░█─ ─░█── ░█▄▄█
|
||||
░█─░█ ▄█▄ ─░█── ░█─░█ ${RITA_VERSION}
|
||||
|
||||
Brought to you by Active CounterMeasures©
|
||||
"
|
||||
|
||||
cat >&2 <<EOF
|
||||
Installation complete!
|
||||
EOF
|
||||
@@ -1,267 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Ansible Install Script
|
||||
# This script installs Ansible on the current system using pipx.
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# cd to the directory where this script is located
|
||||
pushd "$SCRIPT_DIR" > /dev/null
|
||||
|
||||
# load helper functions
|
||||
HELPER_FILE="$SCRIPT_DIR/helper.sh"
|
||||
[[ -f "$HELPER_FILE" ]] || { echo "Helper functions script not found: $HELPER_FILE" >&2; exit 1; }
|
||||
# shellcheck disable=SC1090
|
||||
source "$HELPER_FILE"
|
||||
|
||||
# verify that user has sudo privileges
|
||||
require_sudo
|
||||
|
||||
# enable any needed repositories
|
||||
enable_repositories() {
|
||||
status "Enabling necessary package repositories..."
|
||||
|
||||
if [[ ! -s /etc/os-release ]]; then
|
||||
fail "Unable to read /etc/os-release"
|
||||
else
|
||||
. /etc/os-release
|
||||
case "$ID/$VERSION_ID" in
|
||||
rocky/8*|almalinux/8*)
|
||||
$SUDO dnf config-manager --set-enabled powertools
|
||||
$SUDO dnf install -y epel-release
|
||||
;;
|
||||
rocky/9*)
|
||||
$SUDO dnf config-manager --set-enabled crb
|
||||
$SUDO dnf install -y epel-release
|
||||
;;
|
||||
centos/9)
|
||||
$SUDO dnf config-manager --set-enabled crb
|
||||
$SUDO dnf install -y epel-release epel-next-release
|
||||
;;
|
||||
rhel/8*)
|
||||
$SUDO subscription-manager repos --enable codeready-builder-for-rhel-8-$(arch)-rpms
|
||||
$SUDO dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
|
||||
;;
|
||||
rhel/9*)
|
||||
$SUDO subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
|
||||
$SUDO dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
|
||||
;;
|
||||
ubuntu/*)
|
||||
$SUDO apt update
|
||||
;;
|
||||
*)
|
||||
fail "Unsupported Distribution $ID/$VERSION_ID"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Install a required executable
|
||||
# This function attempts to install a system package only if the corresponding binary does
|
||||
# not already exist in PATH. This is only intended for tools that provide a real executable
|
||||
# $1 = binary name to check for (e.g., "python3", "pip3", "curl")
|
||||
# $2 = space-separated list of package names that provide the binary (preferred packages first)
|
||||
install_tool() {
|
||||
binary="$1"
|
||||
potential_packages="$2"
|
||||
|
||||
# if the binary already exists, nothing to do
|
||||
if type -path "$binary" >/dev/null 2>&1; then
|
||||
status "== $binary executable is already installed"
|
||||
return 0
|
||||
fi
|
||||
|
||||
status "== Installing package that contains $binary"
|
||||
|
||||
# Ubuntu
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
for pkg in $potential_packages; do
|
||||
if ! type -path "$binary" >/dev/null 2>&1; then
|
||||
$SUDO apt-get -q -y install "$pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
# RHEL / CentOS / Rocky / Alma
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
for pkg in $potential_packages; do
|
||||
if ! type -path "$binary" >/dev/null 2>&1; then
|
||||
$SUDO yum -y -q -e 0 install "$pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
else
|
||||
fail "Unable to install packages: unsupported package manager"
|
||||
fi
|
||||
|
||||
# final verification
|
||||
if type -path "$binary" >/dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
echo "WARNING: Unable to install $binary from system package" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_ansible() {
|
||||
# Make sure venv support actually works on this system.
|
||||
if ! python3 -m venv --help >/dev/null 2>&1; then
|
||||
fail "Python venv support is missing on this system. Cannot continue."
|
||||
fi
|
||||
|
||||
# Bootstrap a local virtualenv whose only job is to host pipx,
|
||||
# so we never touch system Python even on PEP 668 distros.
|
||||
python3 -m venv .ansenv || fail "Unable to create Python virtual environment"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source .ansenv/bin/activate
|
||||
|
||||
# Make sure pip in the venv is up to date before installing pipx
|
||||
python3 -m pip install --upgrade pip || fail "Unable to upgrade pip in virtual environment"
|
||||
|
||||
# install pipx into this bootstrap venv
|
||||
python3 -m pip install pipx || fail "Unable to install pipx in virtual environment"
|
||||
|
||||
# ask pipx to ensure ~/.local/bin is added to future shells' PATH
|
||||
pipx ensurepath --prepend || true
|
||||
|
||||
# install a specific, pinned ansible-core via pipx.
|
||||
# pipx will create/own its own venv under ~/.local/pipx/venvs/ansible-core
|
||||
# and expose the entrypoints (ansible, ansible-playbook, ansible-galaxy)
|
||||
# under ~/.local/bin/.
|
||||
pipx install "ansible-core==2.15.13" --force || fail "Unable to install ansible-core with pipx"
|
||||
|
||||
deactivate
|
||||
|
||||
# After deactivating, PATH is restored to its previous value, so any edits we
|
||||
# made inside the venv are lost. Re-ensure ~/.local/bin is on PATH for the rest
|
||||
# of this script so ansible/ansible-playbook/ansible-galaxy are visible.
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.local/bin:"*) ;;
|
||||
*) export PATH="$HOME/.local/bin:$PATH" ;;
|
||||
esac
|
||||
|
||||
# Sanity check: make sure the expected Ansible CLIs are now visible
|
||||
for bin in ansible ansible-playbook ansible-galaxy; do
|
||||
if ! command -v "$bin" >/dev/null 2>&1; then
|
||||
fail "$bin not found in PATH after pipx installation"
|
||||
fi
|
||||
done
|
||||
|
||||
# Link Ansible binaries globally so they work for root, users, cron, and systemd
|
||||
status "Linking Ansible binaries globally..."
|
||||
|
||||
for bin in ansible ansible-playbook ansible-galaxy; do
|
||||
SRC="$(command -v "$bin" || true)"
|
||||
if [ -n "$SRC" ]; then
|
||||
$SUDO ln -sf "$SRC" "/usr/local/bin/$bin"
|
||||
else
|
||||
fail "Unable to locate $bin for global linking"
|
||||
fi
|
||||
done
|
||||
|
||||
# install requisite ansible collections
|
||||
status "Installing required Ansible collections..."
|
||||
ansible-galaxy collection install community.general community.docker --force
|
||||
}
|
||||
|
||||
|
||||
|
||||
# ======== main script starts here ========
|
||||
|
||||
# require sudo privileges
|
||||
require_sudo
|
||||
|
||||
# check if macOS, and install ansible via brew if so
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
# check if ansible is installed
|
||||
which -s ansible
|
||||
if [[ $? != 0 ]] ; then
|
||||
# check if homebrew is installed
|
||||
which -s brew
|
||||
if [[ $? != 0 ]] ; then
|
||||
fail "Homebrew is required to install Ansible."
|
||||
fi
|
||||
# install ansible via homebrew
|
||||
echo "Installing Ansible via brew..."
|
||||
brew install ansible
|
||||
else
|
||||
echo "== Ansible is already installed."
|
||||
fi
|
||||
else # assume linux
|
||||
# enable necessary repositories
|
||||
enable_repositories
|
||||
|
||||
status "Installing required tools..."
|
||||
|
||||
# install python dependencies
|
||||
install_tool python3 "python3"
|
||||
install_tool pip3 "python3-pip"
|
||||
|
||||
# ensure python venv support is available - cannot use install_tool for this since
|
||||
# venv is a module, not a binary
|
||||
# Ensure `python3 -m venv` actually works on Debian/Ubuntu.
|
||||
# On these systems the stdlib venv module requires the extra
|
||||
# `python3-venv` package (which provides ensurepip).
|
||||
# This is safe to run even if it's already installed: `apt-get install`
|
||||
# is idempotent and will return success in that case.
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
status "Ensuring python3-venv is installed for virtualenv support"
|
||||
$SUDO apt-get -q -y install python3-venv
|
||||
fi
|
||||
|
||||
# sanity check after install
|
||||
if ! python3 -m venv --help >/dev/null 2>&1; then
|
||||
fail "python3 venv module is still not available after installation"
|
||||
fi
|
||||
|
||||
# verify that pip is functional
|
||||
if ! python3 -m pip -V >/dev/null 2>&1; then
|
||||
fail "Unable to run python3's pip"
|
||||
fi
|
||||
|
||||
# install other dependencies
|
||||
install_tool wget "wget"
|
||||
install_tool curl "curl"
|
||||
|
||||
# install ansible
|
||||
install_ansible
|
||||
fi
|
||||
|
||||
# ensure /usr/local/bin is in PATH
|
||||
status "Ensuring /usr/local/bin is in PATH..."
|
||||
if ! printf '%s\n' "$PATH" | grep -qE '(^|:)/usr/local/bin(:|$)'; then
|
||||
echo "Adding /usr/local/bin to PATH" >&2
|
||||
|
||||
# For current session
|
||||
export PATH="$PATH:/usr/local/bin"
|
||||
|
||||
# For future logins (prefer system-wide drop-in if available)
|
||||
if [ -d /etc/profile.d ]; then
|
||||
echo 'export PATH="$PATH:/usr/local/bin"' | $SUDO tee /etc/profile.d/local-bin-path.sh >/dev/null
|
||||
elif [ -s /etc/profile ]; then
|
||||
echo 'export PATH="$PATH:/usr/local/bin"' | $SUDO tee -a /etc/profile >/dev/null
|
||||
else
|
||||
echo "Warning: Unable to persist /usr/local/bin in PATH" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# switch back to original working directory
|
||||
popd > /dev/null
|
||||
|
||||
status "Final verification..."
|
||||
# verify the binary is resolvable
|
||||
if ! command -v ansible-playbook >/dev/null 2>&1; then
|
||||
fail "ansible-playbook is not in PATH after installation"
|
||||
fi
|
||||
# verify ansible-playbook executes
|
||||
if ! ansible-playbook --version >/dev/null 2>&1; then
|
||||
fail "ansible-playbook is present but failed to execute"
|
||||
fi
|
||||
# verify ansible-galaxy executes
|
||||
if ! ansible-galaxy --version >/dev/null 2>&1; then
|
||||
fail "ansible-galaxy is present but failed to execute"
|
||||
fi
|
||||
|
||||
status "Ansible installation complete"
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
docker compose "$@"
|
||||
@@ -1,234 +0,0 @@
|
||||
# ansible playbook that performs pre-installation tasks for RITA
|
||||
|
||||
- name: "RITA Pre: System prep and checks"
|
||||
hosts: "{{ install_hosts }}"
|
||||
become: true
|
||||
vars:
|
||||
ansible_python_interpreter: /bin/python3
|
||||
|
||||
# early tasks for checking system compatibility
|
||||
pre_tasks:
|
||||
- name: "RITA Pre: Checking Linux distribution"
|
||||
ansible.builtin.fail:
|
||||
msg: "Distribution {{ ansible_distribution }} is not supported, please see the documentation for supported distributions."
|
||||
when:
|
||||
- ansible_distribution != 'CentOS'
|
||||
- ansible_distribution != 'Rocky'
|
||||
- ansible_distribution != 'Ubuntu'
|
||||
- ansible_distribution != 'RedHat'
|
||||
- ansible_distribution != 'AlmaLinux' #NOTE: legacy support for AlmaLinux 8 only
|
||||
tags:
|
||||
- linux
|
||||
|
||||
- name: "RITA Pre: Checking Linux distribution version"
|
||||
ansible.builtin.fail:
|
||||
msg: "Distribution {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported."
|
||||
when:
|
||||
- >
|
||||
(ansible_distribution == 'Ubuntu' and ansible_distribution_major_version not in ['22', '24']) or
|
||||
(ansible_distribution == 'CentOS' and ansible_distribution_major_version != '9') or
|
||||
(ansible_distribution == 'RedHat' and ansible_distribution_major_version not in ['8', '9']) or
|
||||
(ansible_distribution == 'AlmaLinux' and ansible_distribution_major_version != '8')
|
||||
tags:
|
||||
- linux
|
||||
|
||||
- name: "RITA Pre: Check CPU architecture"
|
||||
ansible.builtin.fail:
|
||||
msg: "CPU architecture {{ ansible_architecture }} is not supported."
|
||||
when: ( ansible_architecture != "x86_64" ) #and ansible_architecture != "aarch64" ) # "aarch64" for pi. #pi0w is armv6l. i386. amd64?
|
||||
|
||||
tasks:
|
||||
# Add repositories
|
||||
# Note that apt-key is deprecated and that directly downloading the key to trusted.gpg.d WITH A .asc EXTENSION is the correct way now.
|
||||
- name: "RITA Pre: Download Docker Ubuntu GPG apt key"
|
||||
block:
|
||||
- name: "RITA Pre: Download Docker Ubuntu GPG apt key with get_url module"
|
||||
get_url:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
dest: /etc/apt/trusted.gpg.d/docker-ubuntu.asc
|
||||
mode: "0644"
|
||||
force: true
|
||||
rescue:
|
||||
- name: "RITA Pre: Download failed with get_url module. Falling back to curl"
|
||||
shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/trusted.gpg.d/docker-ubuntu.asc
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
tags:
|
||||
- packages
|
||||
- linux
|
||||
- linuxdeb
|
||||
|
||||
- name: "RITA Pre: Add Docker Repository to Ubuntu"
|
||||
apt_repository:
|
||||
repo: deb https://download.docker.com/linux/{{ ansible_distribution|lower }} {{ ansible_distribution_release }} stable
|
||||
state: present
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
tags:
|
||||
- packages
|
||||
- linux
|
||||
- linuxdeb
|
||||
|
||||
- name: "RITA Pre: Add Docker Repository to Centos and Rocky distributions" #Alma is included for legacy support
|
||||
yum_repository:
|
||||
name: docker-ce
|
||||
description: Docker package repository
|
||||
gpgkey: https://download.docker.com/linux/centos/gpg
|
||||
baseurl: https://download.docker.com/linux/centos/$releasever/$basearch/stable/
|
||||
state: present
|
||||
enabled: true
|
||||
when: ansible_distribution == 'CentOS' or ansible_distribution == 'Rocky' or ansible_distribution == 'AlmaLinux'
|
||||
tags:
|
||||
- packages
|
||||
- linux
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Pre: Add Docker Repository to RHEL distribution"
|
||||
yum_repository:
|
||||
name: docker-ce
|
||||
description: Docker package repository
|
||||
gpgkey: https://download.docker.com/linux/rhel/gpg
|
||||
baseurl: https://download.docker.com/linux/rhel/$releasever/$basearch/stable/
|
||||
state: present
|
||||
enabled: true
|
||||
when: ansible_distribution == 'RedHat'
|
||||
tags:
|
||||
- packages
|
||||
- linux
|
||||
- linuxrpm
|
||||
|
||||
# Install docker
|
||||
- name: "RITA Pre: Install docker on Ubuntu"
|
||||
block:
|
||||
- name: "RITA Pre: Uninstall unofficial docker packages on Ubuntu"
|
||||
apt:
|
||||
name:
|
||||
- docker-client
|
||||
- docker-client-latest
|
||||
- docker-common
|
||||
- docker-compose
|
||||
- docker-compose-v2
|
||||
- docker-doc
|
||||
- docker-engine
|
||||
- docker-latest
|
||||
- docker-latest-logrotate
|
||||
- docker-logrotate
|
||||
- docker.io
|
||||
- podman-docker
|
||||
state: absent
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxdeb
|
||||
|
||||
- name: "RITA Pre: Install docker-ce on Ubuntu"
|
||||
apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- docker-compose-plugin
|
||||
- containerd.io
|
||||
state: latest
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxdeb
|
||||
|
||||
- name: "RITA Pre: Install docker modules for Python on Ubuntu"
|
||||
apt:
|
||||
name:
|
||||
- python3-docker
|
||||
- python3-requests
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxdeb
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
|
||||
- name: "RITA Pre: Install docker on rpm-based distributions"
|
||||
block:
|
||||
- name: "RITA Pre: Uninstall unofficial docker packages on rpm-based distributions"
|
||||
yum:
|
||||
name:
|
||||
- docker-client
|
||||
- docker-client-latest
|
||||
- docker-common
|
||||
- docker-compose
|
||||
- docker-compose-v2
|
||||
- docker-doc
|
||||
- docker-engine
|
||||
- docker-latest
|
||||
- docker-latest-logrotate
|
||||
- docker-logrotate
|
||||
- docker.io
|
||||
- docker
|
||||
- podman-docker
|
||||
- podman
|
||||
- runc
|
||||
state: absent
|
||||
update_cache: true
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Pre: Install docker-ce on rpm-based distributions"
|
||||
yum:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
- containerd.io
|
||||
state: latest
|
||||
update_cache: true
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxrpm
|
||||
when: ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat' or ansible_distribution == 'Rocky' or ansible_distribution == 'AlmaLinux'
|
||||
|
||||
- name: "RITA Pre: Start and enable docker in systemd"
|
||||
systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: yes
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Pre: Transfer docker-compose script to target system for backwards compatibility"
|
||||
copy:
|
||||
src: docker-compose
|
||||
dest: /usr/local/bin/docker-compose
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# #This keypair will be used for all transfers between all zeek sensors and all achunter systems.
|
||||
# #Note that if there's an existing key it will not be overwritten. Keypair will be placed in the playbook directory.
|
||||
# #Note: formerly used {{ playbook_dir }}
|
||||
# - name: "RITA Pre: Generate ssh keypair for log transfers"
|
||||
# local_action:
|
||||
# module: "user"
|
||||
# name: "{{ lookup('env','USER') }}"
|
||||
# generate_ssh_key: true
|
||||
# ssh_key_type: "rsa"
|
||||
# ssh_key_bits: 4096
|
||||
# ssh_key_file: "{{ lookup('env', 'PWD') }}/id_rsa_dataimport"
|
||||
# # when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
@@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# RITA Install Script
|
||||
# This script installs Ansible and uses it to install RITA and Zeek on a target system.
|
||||
|
||||
RITA_VERSION="REPLACE_ME"
|
||||
_INSTALL_ZEEK=true
|
||||
|
||||
# Function `show_help` displays usage information
|
||||
show_help() {
|
||||
echo "Usage: $0 [--disable-zeek] <target_hostname_or_ip>" >&2
|
||||
echo "Example: $0 127.0.0.1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# No arguments provided
|
||||
if [[ $# -eq 0 ]]; then
|
||||
show_help
|
||||
fi
|
||||
|
||||
# Parse optional flag
|
||||
if [[ "${1:-}" = "--disable-zeek" ]]; then
|
||||
_INSTALL_ZEEK=false
|
||||
shift
|
||||
fi
|
||||
|
||||
# Hostname/IP must now be present
|
||||
if [[ $# -eq 0 ]]; then
|
||||
show_help
|
||||
fi
|
||||
|
||||
install_target="$1"
|
||||
shift
|
||||
|
||||
# If someone puts --disable-zeek after the host, still support it:
|
||||
if [[ "${1:-}" = "--disable-zeek" ]]; then
|
||||
_INSTALL_ZEEK=false
|
||||
shift
|
||||
fi
|
||||
|
||||
# Change working directory to directory of this script
|
||||
pushd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" > /dev/null
|
||||
|
||||
# Load helper functions
|
||||
source ./scripts/helper.sh
|
||||
|
||||
# Install ansible
|
||||
./scripts/ansible-installer.sh
|
||||
|
||||
# Install rita
|
||||
status "Installing rita via ansible on $install_target"
|
||||
if [[ "$install_target" = "localhost" || "$install_target" = "127.0.0.1" || "$install_target" = "::1" ]]; then
|
||||
if [[ "$(uname)" = "Darwin" ]]; then
|
||||
# TODO support macOS install target
|
||||
echo "${YELLOW}Installing RITA via Ansible on the local system is not yet supported on MacOS.${NORMAL}"
|
||||
exit 1
|
||||
fi
|
||||
status "When prompted for a BECOME password, enter your sudo password. If your user does not need one for sudo, just press Enter."
|
||||
if [[ "$_INSTALL_ZEEK" = 'true' ]]; then
|
||||
ansible-playbook --connection=local -K -i "127.0.0.1," -e "install_hosts=127.0.0.1," install_pre.yml install_rita.yml install_zeek.yml
|
||||
else
|
||||
ansible-playbook --connection=local -K -i "127.0.0.1," -e "install_hosts=127.0.0.1," install_pre.yml install_rita.yml
|
||||
fi
|
||||
else
|
||||
status "Setting up future ssh connections to $install_target . You may be asked to provide your ssh password to $install_target ."
|
||||
./scripts/sshprep.sh "$install_target"
|
||||
status "When prompted for a BECOME password, enter your sudo password for $install_target. If your user does not need one for sudo, just press Enter."
|
||||
if [[ "$_INSTALL_ZEEK" = 'true' ]]; then
|
||||
# TODO: fix and re-implement cron setup after RITA#65 is resolved
|
||||
# status "Creating Zeek log transport Cron file"
|
||||
# rm -f zeek_log_transport.cron ; touch zeek_log_transport.cron
|
||||
# #NON_ROOT_ACCOUNT_NAME will be replaced after being placed on the target system (by an ansible recipe in install_zeek.yml
|
||||
# echo "5 * * * * NON_ROOT_ACCOUNT_NAME /usr/local/bin/zeek_log_transport.sh --dest $install_target" >>zeek_log_transport.cron
|
||||
|
||||
ansible-playbook -K -i "${install_target}," -e "install_hosts=${install_target}," install_pre.yml install_rita.yml install_zeek.yml
|
||||
else
|
||||
ansible-playbook -K -i "${install_target}," -e "install_hosts=${install_target}," install_pre.yml install_rita.yml
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
echo \
|
||||
"
|
||||
░█▀▀█ ▀█▀ ▀▀█▀▀ ─█▀▀█
|
||||
░█▄▄▀ ░█─ ─░█── ░█▄▄█
|
||||
░█─░█ ▄█▄ ─░█── ░█─░█ ${RITA_VERSION}
|
||||
|
||||
Brought to you by Active CounterMeasures©
|
||||
"
|
||||
echo "Installation complete!"
|
||||
echo ""
|
||||
|
||||
if [[ "$_INSTALL_ZEEK" = 'true' ]]; then
|
||||
echo "Please run the following commands on any new zeek sensors" >&2
|
||||
echo " zeek start ; zeek enable" >&2
|
||||
echo "" >&2
|
||||
fi
|
||||
|
||||
# switch back to original working directory
|
||||
popd > /dev/null
|
||||
@@ -1,106 +0,0 @@
|
||||
# ansible install playbook for rita
|
||||
|
||||
- name: "RITA Install: RITA installer."
|
||||
hosts: "{{ install_hosts }}"
|
||||
become: true
|
||||
|
||||
vars:
|
||||
rita_version: "REPLACE_ME"
|
||||
rita_container_image: "ghcr.io/activecm/rita:{{ rita_version }}"
|
||||
clickhouse_container_image: clickhouse/clickhouse-server:latest
|
||||
ansible_python_interpreter: /bin/python3
|
||||
|
||||
# the install_pre.yml script should already have been run by this point
|
||||
|
||||
tasks:
|
||||
# make directories
|
||||
- name: "RITA Install: Create configuration directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
loop:
|
||||
- /etc/rita/
|
||||
- /opt/rita/
|
||||
tags:
|
||||
- docker
|
||||
- rita
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# install RITA
|
||||
# the following pulls right from dockerhub. We may not be able to do this if the system is airgapped
|
||||
- name: "RITA Install: Install {{ rita_container_image }} docker image"
|
||||
block:
|
||||
- name: "Pull from Github.io Container repo"
|
||||
community.docker.docker_image:
|
||||
name: "{{ rita_container_image }}"
|
||||
source: pull
|
||||
force_source: true
|
||||
rescue:
|
||||
- name: "RITA Install: Transfer RITA container image to target system"
|
||||
copy:
|
||||
src: "rita-{{ rita_version }}-image.tar"
|
||||
dest: /opt/rita
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
- name: "Install {{ rita_container_name }} container image from file"
|
||||
community.docker.docker_image_load:
|
||||
path: "/opt/rita/rita-{{ rita_version }}-image.tar"
|
||||
register: load_result
|
||||
# this final one prints a list of the loaded images if we use the above 2 stanzas to load from a file
|
||||
- name: "RITA Install: Print loaded image names"
|
||||
ansible.builtin.debug:
|
||||
msg: "Loaded the following images: {{ load_result.image_names | join(', ') }}"
|
||||
tags:
|
||||
- docker
|
||||
- rita
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Install: Transfer rita shell script to target system"
|
||||
copy:
|
||||
src: ./opt/rita.sh
|
||||
dest: /usr/local/bin/rita
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- docker
|
||||
- rita
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Install: Transfer rita install files to /opt/rita"
|
||||
copy:
|
||||
src: ./opt/
|
||||
dest: /opt/rita
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- docker
|
||||
- rita
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
- name: "RITA Install: Transfer rita user files to /etc/rita"
|
||||
copy:
|
||||
src: ./etc/
|
||||
dest: /etc/rita
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- docker
|
||||
- rita
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
@@ -1,216 +0,0 @@
|
||||
# ansible install playbook for docker-zeek
|
||||
|
||||
- name: "Zeek Install: Zeek installer"
|
||||
hosts: "{{ install_hosts }}"
|
||||
become: true
|
||||
|
||||
vars:
|
||||
zeek_version: "REPLACE_ME"
|
||||
zeek_container_image: "activecm/zeek:{{ zeek_version }}"
|
||||
clickhouse_container_image: clickhouse/clickhouse-server:latest
|
||||
ansible_python_interpreter: /bin/python3
|
||||
local_known_hosts: "{{ lookup('env', 'HOME') }}/.ssh/known_hosts"
|
||||
|
||||
# the install_pre.yml script should already have been run by this point
|
||||
|
||||
tasks:
|
||||
# make directories
|
||||
- name: "Zeek Install: Create zeek directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
loop:
|
||||
- /opt/zeek/
|
||||
- /opt/zeek/etc/
|
||||
- /opt/zeek/logs/
|
||||
- /opt/zeek/logs/stats/
|
||||
- /opt/zeek/manual-logs/
|
||||
- /opt/zeek/share/
|
||||
- /opt/zeek/share/zeek/
|
||||
- /opt/zeek/share/zeek/site/
|
||||
- /opt/zeek/share/zeek/site/autoload/
|
||||
- /opt/zeek/spool/
|
||||
- /opt/zeek/spool/installed-scripts-do-not-touch/
|
||||
- /opt/zeek/spool/manager/
|
||||
- /opt/zeek/spool/proxy-1/
|
||||
- /opt/zeek/spool/tmp/
|
||||
tags:
|
||||
- docker
|
||||
- zeek
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# install Zeek
|
||||
# the following pulls right from dockerhub. We may not be able to do this if the system is airgapped
|
||||
- name: "Pull from dockerhub container repo"
|
||||
community.docker.docker_image:
|
||||
name: "{{ zeek_container_image }}"
|
||||
source: pull
|
||||
force_source: true
|
||||
tags:
|
||||
- docker
|
||||
- zeek
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
- name: "Zeek Install: Transfer zeek shell script to target system"
|
||||
copy:
|
||||
src: ./opt/zeek
|
||||
dest: /usr/local/bin/zeek
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- docker
|
||||
- zeek
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Transfer zeek_log_transport.sh shell script to target system."
|
||||
# copy:
|
||||
# src: ./opt/zeek_log_transport.sh
|
||||
# dest: /usr/local/bin/zeek_log_transport.sh
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: 0755
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Transfer zeek_log_transport.cron to target system."
|
||||
# copy:
|
||||
# src: "{{ lookup('env', 'PWD') }}/zeek_log_transport.cron"
|
||||
# dest: /etc/cron.d/zeek_log_transport
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: 0644
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Place name of remote user in zeek_log_transport cron file"
|
||||
# ansible.builtin.replace:
|
||||
# path: /etc/cron.d/zeek_log_transport
|
||||
# regexp: "^(.*)NON_ROOT_ACCOUNT_NAME(.*)$"
|
||||
# replace: '\1{{ lookup("env", "USER") }}\2'
|
||||
# mode: 0644
|
||||
# owner: root
|
||||
# group: root
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
- name: "Zeek Install: check whether node.cfg exists to decide if this is the first time running zeek"
|
||||
stat:
|
||||
path: /opt/zeek/etc/node.cfg
|
||||
register: node_stat
|
||||
|
||||
# this cannot be run on the first install, as zeekcfg needs to be run first to let the user select their interface(s).
|
||||
# the user will need to run this by hand after the install completes.
|
||||
- name: "Zeek Install: Start Zeek"
|
||||
shell: "/usr/local/bin/zeek start"
|
||||
when: (node_stat.stat.exists == true)
|
||||
tags:
|
||||
- docker
|
||||
- hunt
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# this cannot be run on the first install, as zeekcfg needs to be run first to let the user select their interface(s).
|
||||
# the user will need to run this by hand after the install completes.
|
||||
- name: "Zeek Install: Start Zeek on future reboots"
|
||||
shell: "/usr/local/bin/zeek enable"
|
||||
when: (node_stat.stat.exists == true)
|
||||
tags:
|
||||
- docker
|
||||
- hunt
|
||||
- linux
|
||||
- linuxdeb
|
||||
- linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Create .ssh directory."
|
||||
# ansible.builtin.file:
|
||||
# path: "{{ lookup('env', 'HOME') }}/.ssh"
|
||||
# state: directory
|
||||
# owner: "{{ lookup('env', 'USER') }}"
|
||||
# mode: 0700
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Transfer dataimport private key to .ssh"
|
||||
# copy:
|
||||
# src: "{{ lookup('env', 'PWD') }}/id_rsa_dataimport"
|
||||
# dest: "{{ lookup('env', 'HOME') }}/.ssh/"
|
||||
# owner: "{{ lookup('env', 'USER') }}"
|
||||
# mode: 0600
|
||||
# backup: true
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Transfer dataimport public key to .ssh"
|
||||
# copy:
|
||||
# src: "{{ lookup('env', 'PWD') }}/id_rsa_dataimport.pub"
|
||||
# dest: "{{ lookup('env', 'HOME') }}/.ssh/"
|
||||
# owner: "{{ lookup('env', 'USER') }}"
|
||||
# mode: 0644
|
||||
# backup: true
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
|
||||
# TODO: Fix and add this back in after RITA#65 is done
|
||||
# - name: "Zeek Install: Update known_hosts with entries from known_hosts on this system"
|
||||
# ansible.builtin.blockinfile:
|
||||
# block: "{{ lookup('ansible.builtin.file', '{{ local_known_hosts }}') }}"
|
||||
# path: "{{ lookup('env', 'HOME') }}/.ssh/known_hosts"
|
||||
# marker: "# {mark} ANSIBLE MANAGED BLOCK APPENDED DURING ZEEK INSTALL"
|
||||
# owner: "{{ lookup('env', 'USER') }}"
|
||||
# backup: true
|
||||
# create: true
|
||||
# mode: 0644
|
||||
# when: ansible_connection != "local"
|
||||
# tags:
|
||||
# - docker
|
||||
# - zeek
|
||||
# - linux
|
||||
# - linuxdeb
|
||||
# - linuxrpm
|
||||
@@ -1,314 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
askYN() {
|
||||
# Prints a question mark, reads repeatedly until the user
|
||||
# responds with t/T/y/Y or f/F/n/N.
|
||||
TESTYN=""
|
||||
while [ "$TESTYN" != 'Y' ] && [ "$TESTYN" != 'N' ] ; do
|
||||
echo -n '? ' >&2
|
||||
read -e TESTYN <&2 || :
|
||||
case $TESTYN in
|
||||
T*|t*|Y*|y*) TESTYN='Y' ;;
|
||||
F*|f*|N*|n*) TESTYN='N' ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$TESTYN" = 'Y' ]; then
|
||||
return 0 #True
|
||||
else
|
||||
return 1 #False
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
fail() {
|
||||
echo "$@ , exiting." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
require_util() {
|
||||
#Returns true if all binaries listed as parameters exist somewhere in the path, False if one or more missing.
|
||||
while [ -n "$1" ]; do
|
||||
if ! type -path "$1" >/dev/null 2>/dev/null ; then
|
||||
echo Missing utility "$1". Please install it. >&2
|
||||
return 1 #False, app is not available.
|
||||
fi
|
||||
shift
|
||||
done
|
||||
return 0 #True, app is there.
|
||||
} #End of require_util
|
||||
|
||||
|
||||
status() {
|
||||
if [ "$verbose" = 'yes' ]; then
|
||||
echo "== $@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
step() {
|
||||
if [ "$step" = 'yes' ]; then
|
||||
echo "About to $@ , continue" >&2
|
||||
if askYN ; then
|
||||
return
|
||||
else
|
||||
exit 99
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
show_help() {
|
||||
echo "This tool does all the setup needed to ssh to one or more hosts using ssh keys." >&2
|
||||
echo "Usage:" >&2
|
||||
echo >&2
|
||||
echo "$0 [host] [host] [host]..." >&2
|
||||
echo -e "\tDo basic setup and install ssh key on all hosts specified on the command line." >&2
|
||||
echo -e "\tHost may optionally include a username, like bob@www.example.com" >&2
|
||||
echo "$0 -v [host]..." >&2
|
||||
echo -e "\tBe verbose - show steps to be taken." >&2
|
||||
echo "$0 -s [host]..." >&2
|
||||
echo -e "\tSingle step mode - ask permission before making changes (verbose mode is automatically enabled in single step mode)." >&2
|
||||
echo "$0 --authpath /etc/ssh/keys-root/ [host]..." >&2
|
||||
echo -e "\tLocation of the authorized_keys file (useful for VMWare ESXi). This path is used for _all_ hosts on this command line." >&2
|
||||
echo "$0 -h" >&2
|
||||
echo "$0 --help" >&2
|
||||
echo -e "\tShow this help text." >&2
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
load_params() {
|
||||
target_list=''
|
||||
|
||||
if [ "z$1" = "z" ]; then
|
||||
echo "No target systems requested, this will perform basic ssh setup only." >&2
|
||||
fi
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-v|--verbose)
|
||||
verbose='yes'
|
||||
;;
|
||||
-s|--step)
|
||||
verbose='yes'
|
||||
step='yes'
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
--authpath)
|
||||
authpath="$2"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
target_list="$target_list $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
check_requirements() {
|
||||
status "Checking system requirements"
|
||||
require_util awk basename chmod cp date dig egrep head mkdir mktemp ssh ssh-add ssh-keygen touch uniq || fail "Missing one or more tools, please install and rerun"
|
||||
step "perform system checks"
|
||||
mkdir -p "$HOME/.ssh"
|
||||
chmod -R go-rwx "$HOME/.ssh"
|
||||
if [ -z "$SSH_AUTH_SOCK" ] || [ ! -S "$SSH_AUTH_SOCK" ]; then
|
||||
fail 'We do not appear to have an ssh-agent to talk to. You may want to add the following 3 lines to ~/.bashrc on this system :
|
||||
if [ -z "$SSH_AUTH_SOCK" ] || [ ! -S "$SSH_AUTH_SOCK" ]; then
|
||||
eval $(ssh-agent -s)
|
||||
fi
|
||||
(and then logout, log back in, and try again.)'
|
||||
fi
|
||||
[ -w "$HOME/.ssh" ] || fail "User .ssh directory does not appear to be writeable"
|
||||
[ -s "$HOME/.ssh/config" ] || touch "$HOME/.ssh/config"
|
||||
}
|
||||
|
||||
|
||||
check_key() {
|
||||
status "Checking that we have a keypair available to load into the agent"
|
||||
#Confirm we have an ssh RSA keypair; create if not.
|
||||
|
||||
if [ ! -s "$HOME/.ssh/id_rsa" ] && [ ! -s "$HOME/.ssh/id_rsa.pub" ]; then
|
||||
status "No SSH RSA keypair, creating one. We strongly encourage you to provide a strong passphrase."
|
||||
step "create ssh rsa keypair"
|
||||
ssh-keygen -t rsa-sha2-512 -b 4096 -f "$HOME/.ssh/id_rsa" #We don't force the comment; "user@host" is the default
|
||||
|
||||
elif [ -s "$HOME/.ssh/id_rsa" ] && [ ! -s "$HOME/.ssh/id_rsa.pub" ]; then
|
||||
status "private key available but no public; we'll create the public key. You will be asked for your id_rsa private key passphrase."
|
||||
step "regenerate public key from private"
|
||||
ssh-keygen -y -f "$HOME/.ssh/id_rsa" >"$HOME/.ssh/id_rsa.pub"
|
||||
elif [ ! -s "$HOME/.ssh/id_rsa" ] && [ -s "$HOME/.ssh/id_rsa.pub" ]; then
|
||||
status "Public key available, but no private"
|
||||
fail "Missing private key, please provide $HOME/.ssh/id_rsa"
|
||||
elif [ -s "$HOME/.ssh/id_rsa" ] && [ -s "$HOME/.ssh/id_rsa.pub" ]; then
|
||||
status "Both private and public keys available"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
check_agent() {
|
||||
status "Checking that keys are loaded into the agent"
|
||||
#Confirm we have at least one key loaded into ssh-agent.
|
||||
|
||||
if [ $(ssh-add -l | wc -l) -eq 0 ] || [ "$(ssh-add -l)" = 'The agent has no identities.' ]; then
|
||||
#No keys currently loaded into the agent, load at least one
|
||||
[ -s "$HOME/.ssh/id_rsa" -a -s "$HOME/.ssh/id_rsa.pub" ] || check_key
|
||||
status "About to load keys into ssh-agent; you may be asked for your passphrase(s)"
|
||||
step "load keys into agent"
|
||||
ssh-add
|
||||
fi
|
||||
|
||||
if [ $(ssh-add -l | wc -l) -eq 0 ] || [ "$(ssh-add -l)" = 'The agent has no identities.' ]; then
|
||||
fail "Unable to get any keys into the ssh-agent"
|
||||
fi
|
||||
|
||||
status "ssh-agent has at least one key loaded, continuing"
|
||||
}
|
||||
|
||||
|
||||
prepend_config_block() {
|
||||
#We prepend new stanzas since the end of the file may contain a default stanza like "Host * ......"
|
||||
|
||||
if [ -s "$HOME/.ssh/config" ]; then
|
||||
cp -p "$HOME/.ssh/config" "$HOME/.ssh/config.$(date '+%Y%m%d%H%M%S%N')"
|
||||
elif [ ! -e "$HOME/.ssh/config" ]; then
|
||||
touch "$HOME/.ssh/config"
|
||||
fi
|
||||
|
||||
new_config=$(mktemp -q /tmp/$(basename $0).XXXXXX) || fail "Unable to make temporary file during ~/.ssh/config update."
|
||||
echo -e "$1" >"$new_config"
|
||||
cat "$HOME/.ssh/config" >>"$new_config"
|
||||
step "move new config file ($new_config) over existing $HOME/.ssh/config"
|
||||
mv "$new_config" "$HOME/.ssh/config"
|
||||
}
|
||||
|
||||
|
||||
check_config_block() {
|
||||
#Make sure we have a config block for this host, and add one if not
|
||||
#Param 1: user, Param 2: host, Param 3: optional hostname or ip address to use as "Hostname"
|
||||
|
||||
status "Checking if we have a config block for $2"
|
||||
if [ -n "$1" ]; then
|
||||
user_line=" User ${1}"
|
||||
else
|
||||
user_line=''
|
||||
fi
|
||||
|
||||
if egrep -q "(^Host.*[[:space:]]${2}[[:space:]]|^Host.*[[:space:]]${2}\$)" "$HOME/.ssh/config" ; then
|
||||
status "$2 has a configuration block in ~/.ssh/config"
|
||||
else
|
||||
status "$2 does not have a configuration block in ~/.ssh/config, adding one."
|
||||
if [ -n "$3" ]; then
|
||||
status "User-supplied target IP or hostname ($3) for $2"
|
||||
prepend_config_block "\nHost ${2} ${3}\n\tHostname\t\t${3}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
elif [ -n "$(which getent 2>/dev/null)" ] && [ -n "$(getent hosts "$2")" ]; then
|
||||
status "running on non-mac, appears we have an entry in /etc/hosts"
|
||||
ip4=$(getent ahostsv4 "$2" | awk '{print $1}' | uniq | head -1)
|
||||
ip6=$(getent ahostsv6 "$2" | awk '{print $1}' | uniq | head -1)
|
||||
|
||||
if [ -n "$ip4" -a -n "$ip6" ]; then
|
||||
status "Have both ipv4 and ipv6 addresses for $2, adding both blocks"
|
||||
prepend_config_block "\nHost ${2} ${ip4}\n\tHostname\t\t$ip4\n\tHostKeyAlias\t\t${2}\n${user_line}\n\nHost ${2}-v6 ${ip6}\n\tHostname\t\t$ip6\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
elif [ -n "$ip4" -o -n "$ip6" ]; then #One or the other but not both, which is why we can have both ip4 and ip6 on the Hostname line.
|
||||
prepend_config_block "\nHost ${2} ${ip4}${ip6}\n\tHostname\t\t${ip4}${ip6}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
#We don't include a block for neither ip4 nor ip6 set as "getent hosts" did successfully get one or the other.
|
||||
fi
|
||||
elif [ -n "$(which dscacheutil 2>/dev/null)" ] && [ -n "$(dscacheutil -q host -a name "$2")" ]; then
|
||||
status "running on mac, appears we have an entry in /etc/hosts"
|
||||
local_ip=$(dscacheutil -q host -a name "$2" | grep '^ip_address' | awk '{print $2}')
|
||||
prepend_config_block "\nHost ${2} ${local_ip}\n\tHostname\t\t${local_ip}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
else
|
||||
status "No user-supplied target IP or hostname for $2, look one up"
|
||||
ip4=$(dig +nocomment +short ${2} A 2>/dev/null | sed -e 's/;;.*//' | grep -v '^$' | head -1)
|
||||
ip6=$(dig +nocomment +short ${2} AAAA 2>/dev/null | sed -e 's/;;.*//' | grep -v '^$' | head -1)
|
||||
|
||||
if [ -n "$ip4" ]; then
|
||||
if [ -n "$ip6" ]; then
|
||||
status "Have both ipv4 and ipv6 addresses for $2, adding both blocks"
|
||||
prepend_config_block "\nHost ${2} ${ip4}\n\tHostname\t\t${ip4}\n\tHostKeyAlias\t\t${2}\n${user_line}\n\nHost ${2}-v6 ${ip6}\n\tHostname\t\t${ip6}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
else
|
||||
status "Have an IPv4 address only for $2"
|
||||
prepend_config_block "\nHost ${2} ${ip4}\n\tHostname\t\t${ip4}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
fi
|
||||
else
|
||||
if [ -n "$ip6" ]; then
|
||||
status "Have an ipv6 address only for $2"
|
||||
prepend_config_block "\nHost ${2} ${2}-v6 ${ip6}\n\tHostname\t\t${ip6}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
else
|
||||
#echo "== No ipv4 or ipv6 address found for ${2}. Please enter an IP address to use:" >&2
|
||||
#read ip_or_hostname <&2
|
||||
#if [ -z "$ip_or_hostname" ]; then
|
||||
# ip_or_hostname="$2"
|
||||
#fi
|
||||
status "We could not lookup a DNS address for $2 so we will just use $2 in the ssh Hostname field."
|
||||
ip_or_hostname="$2"
|
||||
prepend_config_block "\nHost ${2} ${ip_or_hostname}\n\tHostname\t\t${ip_or_hostname}\n\tHostKeyAlias\t\t${2}\n${user_line}\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
sshprep_main() {
|
||||
load_params "$@"
|
||||
check_requirements
|
||||
check_agent
|
||||
|
||||
status "Retrieving public key(s)"
|
||||
pub_key_content="$(ssh-add -L)"
|
||||
|
||||
retval=0
|
||||
for one_target in $target_list ; do
|
||||
step "start setting up $one_target"
|
||||
status "Setting up ssh connection to $one_target"
|
||||
if echo "$one_target" | grep -q '@' - ; then
|
||||
#We have an "@" in the target, so this is "user@host"
|
||||
one_user="${one_target%%@*}"
|
||||
one_host="${one_target##*@}"
|
||||
else
|
||||
#No "@" in target, so this is just a host
|
||||
one_user=''
|
||||
one_host="$one_target"
|
||||
fi
|
||||
|
||||
#Check if we have a config block for this target; create one if not, place at top of file
|
||||
check_config_block "$one_user" "$one_host" #FIXME - arrange a way for the user to supply an optional hostname/ip as param3
|
||||
|
||||
status "Checking that we can now connect without using a password."
|
||||
status "If this is your first time connecting to $one_target, you may be asked to verify a fingerprint. To see the correct value, run 'ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub' on that system's console."
|
||||
step "confirm $one_target reachable by key"
|
||||
if ssh -o 'PasswordAuthentication=no' -o 'PreferredAuthentications=publickey' "$one_target" 'touch .ssh/reached-by-key ; true' 2>/dev/null ; then
|
||||
status "Key appears to be successfully installed on $one_target"
|
||||
else
|
||||
status "Sending public key(s) over to $one_target . You may be asked for your password for this account."
|
||||
step "send public keys over to $one_target"
|
||||
if [ -n "$authpath" ]; then
|
||||
echo "$pub_key_content" \
|
||||
| ssh "$one_target" 'mkdir -p '"$authpath"' ; cat >>'"$authpath"'/authorized_keys ; chmod go-rwx '"$authpath"' '"$authpath"'/authorized_keys'
|
||||
else
|
||||
echo "$pub_key_content" \
|
||||
| ssh "$one_target" 'mkdir -p .ssh ; cat >>.ssh/authorized_keys ; chmod go-rwx ./ .ssh/ .ssh/authorized_keys'
|
||||
fi
|
||||
|
||||
step "confirm $one_target reachable by key"
|
||||
if ssh -o 'PasswordAuthentication=no' -o 'PreferredAuthentications=publickey' "$one_target" 'touch .ssh/reached-by-key ; true' 2>/dev/null ; then
|
||||
status "Key is now successfully installed on $one_target"
|
||||
else
|
||||
status "Unable to reach $one_target by ssh key."
|
||||
retval=2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit "$retval"
|
||||
}
|
||||
|
||||
|
||||
sshprep_main "$@"
|
||||
+14
-17
@@ -1,12 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# dev script for testing the installer on a remote droplet.
|
||||
# generates the installer, copies it to the droplet, runs it, then runs tests.
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RITA_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
droplet_ip="$1"
|
||||
if [[ -z "$droplet_ip" ]]; then
|
||||
echo "droplet ip was not provided"
|
||||
echo "Usage: $0 <droplet_ip>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -16,30 +19,24 @@ if VERSION="$(git -C "$RITA_DIR" describe --tags --exact-match 2>/dev/null)"; th
|
||||
elif VERSION="$(git -C "$RITA_DIR" describe --tags --dirty --always 2>/dev/null)"; then
|
||||
: # dev
|
||||
else
|
||||
fail "Unable to determine RITA_VERSION."
|
||||
echo "Unable to determine RITA_VERSION." >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ -n "$VERSION" ]] || { echo "Unable to determine RITA_VERSION." >&2; exit 1; }
|
||||
|
||||
# generate dev installer (bundles Docker images for offline install)
|
||||
"${SCRIPT_DIR}/create-dev-installer.sh"
|
||||
|
||||
# generate installer
|
||||
"${SCRIPT_DIR}/generate_installer.sh"
|
||||
INSTALLER_TARBALL="${SCRIPT_DIR}/rita-${VERSION}.tar.gz"
|
||||
[[ -f "$INSTALLER_TARBALL" ]] || { echo "RITA installer tarball not found." >&2; exit 1; }
|
||||
|
||||
INSTALLER_DIR="${SCRIPT_DIR}/rita-${VERSION}-installer"
|
||||
|
||||
# verify tar ball exists
|
||||
[[ -f "${INSTALLER_DIR}.tar.gz" ]] || { echo "RITA installer tarball not found." >&2; exit 1; }
|
||||
tar -xf "${INSTALLER_DIR}.tar.gz"
|
||||
[[ -f "${INSTALLER_DIR}/install_rita.sh" ]] || { echo "RITA installer script not found." >&2; exit 1; }
|
||||
"${INSTALLER_DIR}/install_rita.sh" "root@$droplet_ip"
|
||||
|
||||
# # # # ansible-playbook -i digitalocean_inventory.py -e "install_hosts=${droplet_ip}" "./rita-${VERSION}-installer/install_rita.yml"
|
||||
# copy tarball to droplet, extract, and run
|
||||
scp "$INSTALLER_TARBALL" "root@$droplet_ip":/root/
|
||||
ssh -t "root@$droplet_ip" "cd /root && tar -xf rita-${VERSION}.tar.gz && cd rita-${VERSION}-installer && ./install_rita.sh"
|
||||
|
||||
# copy over test data
|
||||
scp -r "${RITA_DIR}/test_data/open_sni" "root@$droplet_ip":/root/sample_logs
|
||||
|
||||
# # copy over test script
|
||||
# copy over test script and run it
|
||||
scp "${SCRIPT_DIR}/test_installed.sh" "root@$droplet_ip":/root/test_installed.sh
|
||||
|
||||
# run test script
|
||||
ssh -t "root@$droplet_ip" /root/test_installed.sh "$VERSION"
|
||||
#
|
||||
Reference in New Issue
Block a user