mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 09:12:45 +01:00
Merge pull request #14650 from Security-Onion-Solutions/hotfix/2.4.150
Hotfix 2.4.150
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
### 2.4.150-20250512 ISO image released on 2025/05/12
|
### 2.4.150-20250522 ISO image released on 2025/05/22
|
||||||
|
|
||||||
|
|
||||||
### Download and Verify
|
### Download and Verify
|
||||||
|
|
||||||
2.4.150-20250512 ISO image:
|
2.4.150-20250522 ISO image:
|
||||||
https://download.securityonion.net/file/securityonion/securityonion-2.4.150-20250512.iso
|
https://download.securityonion.net/file/securityonion/securityonion-2.4.150-20250522.iso
|
||||||
|
|
||||||
MD5: 7A7469A7A38EA9A2DB770C36AE36A0CA
|
MD5: 239E69B83072BBF2602D4043FE53A160
|
||||||
SHA1: 7E768D515353F339DC536DED6207B786DAFF7D27
|
SHA1: C62893D3C7F5592665BFDCBC9A45BB20A926F9A8
|
||||||
SHA256: F8B2EB6B332F2367F0C097D211577565C8FB5CC7809E97D63687C634035B3699
|
SHA256: 2ADE037C7FD34591030B1FAC10392C4E6613F152DD24BFBD897E57EE300895B9
|
||||||
|
|
||||||
Signature for ISO image:
|
Signature for ISO image:
|
||||||
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.150-20250512.iso.sig
|
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.150-20250522.iso.sig
|
||||||
|
|
||||||
Signing key:
|
Signing key:
|
||||||
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
|
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
|
||||||
@@ -25,22 +25,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.
|
|||||||
|
|
||||||
Download the signature file for the ISO:
|
Download the signature file for the ISO:
|
||||||
```
|
```
|
||||||
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.150-20250512.iso.sig
|
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.150-20250522.iso.sig
|
||||||
```
|
```
|
||||||
|
|
||||||
Download the ISO image:
|
Download the ISO image:
|
||||||
```
|
```
|
||||||
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.150-20250512.iso
|
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.150-20250522.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
Verify the downloaded ISO image using the signature file:
|
Verify the downloaded ISO image using the signature file:
|
||||||
```
|
```
|
||||||
gpg --verify securityonion-2.4.150-20250512.iso.sig securityonion-2.4.150-20250512.iso
|
gpg --verify securityonion-2.4.150-20250522.iso.sig securityonion-2.4.150-20250522.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
|
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
|
||||||
```
|
```
|
||||||
gpg: Signature made Fri 09 May 2025 06:27:29 PM EDT using RSA key ID FE507013
|
gpg: Signature made Thu 22 May 2025 11:15:06 AM EDT using RSA key ID FE507013
|
||||||
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
|
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
|
||||||
gpg: WARNING: This key is not certified with a trusted signature!
|
gpg: WARNING: This key is not certified with a trusted signature!
|
||||||
gpg: There is no indication that the signature belongs to the owner.
|
gpg: There is no indication that the signature belongs to the owner.
|
||||||
|
|||||||
@@ -4,22 +4,16 @@
|
|||||||
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
import sys, argparse, re, subprocess, json
|
||||||
|
|
||||||
|
|
||||||
import sys, argparse, re, docker
|
|
||||||
from packaging.version import Version, InvalidVersion
|
from packaging.version import Version, InvalidVersion
|
||||||
from itertools import groupby, chain
|
from itertools import groupby, chain
|
||||||
|
|
||||||
|
|
||||||
def get_image_name(string) -> str:
|
def get_image_name(string) -> str:
|
||||||
return ':'.join(string.split(':')[:-1])
|
return ':'.join(string.split(':')[:-1])
|
||||||
|
|
||||||
|
|
||||||
def get_so_image_basename(string) -> str:
|
def get_so_image_basename(string) -> str:
|
||||||
return get_image_name(string).split('/so-')[-1]
|
return get_image_name(string).split('/so-')[-1]
|
||||||
|
|
||||||
|
|
||||||
def get_image_version(string) -> str:
|
def get_image_version(string) -> str:
|
||||||
ver = string.split(':')[-1]
|
ver = string.split(':')[-1]
|
||||||
if ver == 'latest':
|
if ver == 'latest':
|
||||||
@@ -35,56 +29,75 @@ def get_image_version(string) -> str:
|
|||||||
return '999999.9.9'
|
return '999999.9.9'
|
||||||
return ver
|
return ver
|
||||||
|
|
||||||
|
def run_command(command):
|
||||||
|
process = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
|
if process.returncode != 0:
|
||||||
|
print(f"Error executing command: {command}", file=sys.stderr)
|
||||||
|
print(f"Error message: {process.stderr}", file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
return process.stdout
|
||||||
|
|
||||||
def main(quiet):
|
def main(quiet):
|
||||||
client = docker.from_env()
|
|
||||||
|
|
||||||
# Prune old/stopped containers
|
|
||||||
if not quiet: print('Pruning old containers')
|
|
||||||
client.containers.prune()
|
|
||||||
|
|
||||||
image_list = client.images.list(filters={ 'dangling': False })
|
|
||||||
|
|
||||||
# Map list of image objects to flattened list of tags (format: "name:version")
|
|
||||||
tag_list = list(chain.from_iterable(list(map(lambda x: x.attrs.get('RepoTags'), image_list))))
|
|
||||||
|
|
||||||
# Filter to only SO images (base name begins with "so-")
|
|
||||||
tag_list = list(filter(lambda x: re.match(r'^.*\/so-[^\/]*$', get_image_name(x)), tag_list))
|
|
||||||
|
|
||||||
# Group tags into lists by base name (sort by same projection first)
|
|
||||||
tag_list.sort(key=lambda x: get_so_image_basename(x))
|
|
||||||
grouped_tag_lists = [ list(it) for _, it in groupby(tag_list, lambda x: get_so_image_basename(x)) ]
|
|
||||||
|
|
||||||
no_prunable = True
|
|
||||||
for t_list in grouped_tag_lists:
|
|
||||||
try:
|
try:
|
||||||
# Group tags by version, in case multiple images exist with the same version string
|
# Prune old/stopped containers using docker CLI
|
||||||
t_list.sort(key=lambda x: Version(get_image_version(x)), reverse=True)
|
if not quiet: print('Pruning old containers')
|
||||||
grouped_t_list = [ list(it) for _,it in groupby(t_list, lambda x: get_image_version(x)) ]
|
run_command('docker container prune -f')
|
||||||
|
|
||||||
# Keep the 2 most current version groups
|
# Get list of images using docker CLI
|
||||||
if len(grouped_t_list) <= 2:
|
images_json = run_command('docker images --format "{{json .}}"')
|
||||||
continue
|
|
||||||
else:
|
# Parse the JSON output
|
||||||
no_prunable = False
|
image_list = []
|
||||||
for group in grouped_t_list[2:]:
|
for line in images_json.strip().split('\n'):
|
||||||
for tag in group:
|
if line: # Skip empty lines
|
||||||
if not quiet: print(f'Removing image {tag}')
|
image_list.append(json.loads(line))
|
||||||
|
|
||||||
|
# Extract tags in the format "name:version"
|
||||||
|
tag_list = []
|
||||||
|
for img in image_list:
|
||||||
|
# Skip dangling images
|
||||||
|
if img.get('Repository') != "<none>" and img.get('Tag') != "<none>":
|
||||||
|
tag = f"{img.get('Repository')}:{img.get('Tag')}"
|
||||||
|
# Filter to only SO images (base name begins with "so-")
|
||||||
|
if re.match(r'^.*\/so-[^\/]*$', get_image_name(tag)):
|
||||||
|
tag_list.append(tag)
|
||||||
|
|
||||||
|
# Group tags into lists by base name (sort by same projection first)
|
||||||
|
tag_list.sort(key=lambda x: get_so_image_basename(x))
|
||||||
|
grouped_tag_lists = [list(it) for k, it in groupby(tag_list, lambda x: get_so_image_basename(x))]
|
||||||
|
|
||||||
|
no_prunable = True
|
||||||
|
for t_list in grouped_tag_lists:
|
||||||
try:
|
try:
|
||||||
client.images.remove(tag, force=True)
|
# Group tags by version, in case multiple images exist with the same version string
|
||||||
except docker.errors.ClientError as e:
|
t_list.sort(key=lambda x: Version(get_image_version(x)), reverse=True)
|
||||||
print(f'Could not remove image {tag}, continuing...')
|
grouped_t_list = [list(it) for k, it in groupby(t_list, lambda x: get_image_version(x))]
|
||||||
except (docker.errors.APIError, InvalidVersion) as e:
|
# Keep the 2 most current version groups
|
||||||
print(f'so-{get_so_image_basename(t_list[0])}: {e}', file=sys.stderr)
|
if len(grouped_t_list) <= 2:
|
||||||
exit(1)
|
continue
|
||||||
|
else:
|
||||||
|
no_prunable = False
|
||||||
|
for group in grouped_t_list[2:]:
|
||||||
|
for tag in group:
|
||||||
|
if not quiet: print(f'Removing image {tag}')
|
||||||
|
try:
|
||||||
|
run_command(f'docker rmi -f {tag}')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Could not remove image {tag}, continuing...')
|
||||||
|
except (InvalidVersion) as e:
|
||||||
|
print(f'so-{get_so_image_basename(t_list[0])}: {e}', file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print('Unhandled exception occurred:')
|
||||||
|
print(f'so-{get_so_image_basename(t_list[0])}: {e}', file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if no_prunable and not quiet:
|
||||||
|
print('No Security Onion images to prune')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Unhandled exception occurred:')
|
print(f"Error: {e}", file=sys.stderr)
|
||||||
print(f'so-{get_so_image_basename(t_list[0])}: {e}', file=sys.stderr)
|
exit(1)
|
||||||
exit(1)
|
|
||||||
|
|
||||||
if no_prunable and not quiet:
|
|
||||||
print('No Security Onion images to prune')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main_parser = argparse.ArgumentParser(add_help=False)
|
main_parser = argparse.ArgumentParser(add_help=False)
|
||||||
|
|||||||
BIN
sigs/securityonion-2.4.150-20250522.iso.sig
Normal file
BIN
sigs/securityonion-2.4.150-20250522.iso.sig
Normal file
Binary file not shown.
Reference in New Issue
Block a user