Private
Public Access
1
0

Merge develop into master for v1.0.0 release

This commit is contained in:
2026-04-14 13:34:19 +00:00
9 changed files with 302 additions and 102 deletions

View File

@ -26,70 +26,66 @@ jobs:
- name: Check formatting - name: Check formatting
run: cargo fmt --all -- --check run: cargo fmt --all -- --check
# TEMPORARILY DISABLED - re-enable after build jobs are stable clippy:
# clippy: name: Clippy Lints
# name: Clippy Lints runs-on: linux
# runs-on: linux container: node:18
# container: node:18 steps:
# steps: - uses: actions/checkout@v4
# - uses: actions/checkout@v2 with:
# with: fetch-depth: 0
# fetch-depth: 0 - name: Install system dependencies
# - name: Install system dependencies run: |
# run: | apt-get update
# apt-get update apt-get install -y libsystemd-dev pkg-config
# apt-get install -y libsystemd-dev pkg-config - uses: dtolnay/rust-toolchain@stable
# - uses: dtolnay/rust-toolchain@stable with:
# with: components: clippy
# components: clippy - name: Cache cargo
# - name: Cache cargo uses: Swatinem/rust-cache@v2
# uses: Swatinem/rust-cache@v2 - name: Run clippy
# - name: Run clippy run: cargo clippy --all-targets --all-features -- -D warnings
# run: cargo clippy --all-targets --all-features -- -D warnings
# test:
# test: name: Unit Tests
# name: Unit Tests runs-on: linux
# runs-on: linux container: node:18
# container: node:18 steps:
# steps: - uses: actions/checkout@v4
# - uses: actions/checkout@v2 with:
# with: fetch-depth: 0
# fetch-depth: 0 - name: Install system dependencies
# - name: Install system dependencies run: |
# run: | apt-get update
# apt-get update apt-get install -y libsystemd-dev pkg-config
# apt-get install -y libsystemd-dev pkg-config - uses: dtolnay/rust-toolchain@stable
# - uses: dtolnay/rust-toolchain@stable - name: Cache cargo
# - name: Cache cargo uses: Swatinem/rust-cache@v2
# uses: Swatinem/rust-cache@v2 - name: Run tests
# - name: Run tests run: cargo test --all-features
# run: cargo test --all-features
# - name: Upload coverage audit:
# uses: codecov/codecov-action@v4 name: Security Audit
# if: always() runs-on: linux
# container: node:18
# audit: steps:
# name: Security Audit - uses: actions/checkout@v4
# runs-on: linux with:
# container: node:18 fetch-depth: 0
# steps: - name: Install system dependencies
# - uses: actions/checkout@v2 run: |
# with: apt-get update
# fetch-depth: 0 apt-get install -y libsystemd-dev pkg-config
# - name: Install system dependencies - uses: dtolnay/rust-toolchain@stable
# run: | - name: Run cargo-audit
# apt-get update run: |
# apt-get install -y libsystemd-dev pkg-config cargo install cargo-audit
# - uses: dtolnay/rust-toolchain@stable cargo audit
# - name: Run cargo-audit
# run: |
# cargo install cargo-audit
# cargo audit
# Debian/Ubuntu Package Build
build-deb: build-deb:
name: Build Debian Package name: Build Debian Package
runs-on: linux runs-on: linux
container: debian:bookworm container: node:18-bookworm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -113,7 +109,7 @@ jobs:
build-rpm: build-rpm:
name: Build RPM Package name: Build RPM Package
runs-on: linux runs-on: linux
container: fedora:latest container: linux-patch-api-rpm:latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -121,7 +117,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
- name: Install RPM build tools - name: Install RPM build tools
run: | run: |
dnf install -y rpm-build gcc cargo rust libsystemd-devel pkgconfig-pkg-config dnf install -y rpm-build gcc cargo rust systemd-devel pkg-config
- name: Build release binary - name: Build release binary
run: cargo build --release run: cargo build --release
- name: Build RPM package - name: Build RPM package
@ -136,14 +132,22 @@ jobs:
build-apk: build-apk:
name: Build Alpine Package name: Build Alpine Package
runs-on: linux runs-on: linux
container: alpine:latest container: node:18-alpine
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Rust toolchain (rustup for edition2024 support)
run: |
apk add --no-cache curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
source $HOME/.cargo/env
rustc --version
cargo --version
- name: Install build dependencies - name: Install build dependencies
run: | run: |
apk add --no-cache rust cargo musl-dev openssl-dev systemd-dev git abuild apk add --no-cache musl-dev openssl-dev git abuild gcc elogind-dev
# NOTE: abuild-keygen is now done inside build-alpine.sh to ensure keys persist in same shell session
- name: Build APK package - name: Build APK package
run: ./build-alpine.sh run: ./build-alpine.sh
- name: Upload to releases (on tag) - name: Upload to releases (on tag)
@ -156,7 +160,7 @@ jobs:
build-arch: build-arch:
name: Build Arch Package name: Build Arch Package
runs-on: linux runs-on: linux
container: archlinux:latest container: linux-patch-api-arch:latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@ -2,7 +2,7 @@
## System Overview ## System Overview
The Linux_Patch_API is a secure, single-host API service that enables remote package and patch management on Linux systems. Each instance runs as a systemd service on the managed host, providing a REST API over mTLS with strict IP whitelist enforcement. The Linux_Patch_API is a secure, single-host API service that enables remote package and patch management on Linux systems. Each instance runs as a system service on the managed host (systemd on most distributions, OpenRC on Alpine), providing a REST API over mTLS with strict IP whitelist enforcement.
**Architecture Type:** Agent Per Host (Option B) **Architecture Type:** Agent Per Host (Option B)
**Deployment:** One instance per managed Linux host **Deployment:** One instance per managed Linux host
@ -45,8 +45,9 @@ The Linux_Patch_API is a secure, single-host API service that enables remote pac
- Distribution detection and adapter selection - Distribution detection and adapter selection
6. **Audit Logger** 6. **Audit Logger**
- systemd journal integration (primary) - System logging integration (primary)
- Optional remote syslog server - systemd journal on systemd-based systems
- syslog/local files on OpenRC-based systems
- Local file fallback (`/var/log/linux_patch_api/`) - Local file fallback (`/var/log/linux_patch_api/`)
- 30-day retention with daily rotation and gzip compression - 30-day retention with daily rotation and gzip compression
@ -59,9 +60,10 @@ The Linux_Patch_API is a secure, single-host API service that enables remote pac
### External Integrations ### External Integrations
- **Package Managers:** apt, dnf, yum, apk, pacman (via system commands) - **Package Managers:** apt, dnf, yum, apk, pacman (via system commands)
- **systemd:** Service management and journal logging - **Init System:** Service management and logging
- systemd (Debian, Ubuntu, RHEL, CentOS, Fedora)
- OpenRC (Alpine Linux)
- **Internal CA:** Certificate validation against self-hosted CA - **Internal CA:** Certificate validation against self-hosted CA
- **Remote Syslog:** Optional external log aggregation
--- ---
@ -74,14 +76,17 @@ The Linux_Patch_API is a secure, single-host API service that enables remote pac
- **mTLS:** Rust TLS library (rustls or native-tls) - **mTLS:** Rust TLS library (rustls or native-tls)
### Infrastructure ### Infrastructure
- **Service Manager:** systemd - **Service Manager:** Distribution-dependent
- systemd (most distributions)
- OpenRC (Alpine Linux)
- **Configuration:** YAML - **Configuration:** YAML
- **Logging:** systemd journal + optional syslog
### Deployment ### Deployment
- **Package Format:** Native Linux packages (deb, rpm, apk, pkg.tar.zst) - **Package Format:** Native Linux packages (deb, rpm, apk, pkg.tar.zst)
- **Distribution:** Via target system package manager (apt, dnf, apk, pacman) - **Distribution:** Via target system package manager (apt, dnf, apk, pacman)
- **Installation:** Package installs binary, systemd service, and default config structure - **Installation:** Package installs binary, init script/service, and default config structure
- systemd unit file for systemd distributions
- OpenRC init script for Alpine
- **Updates:** Handled through system package manager - **Updates:** Handled through system package manager
--- ---
@ -99,16 +104,21 @@ The Linux_Patch_API is a secure, single-host API service that enables remote pac
- No granular permissions (binary access: allowed or denied) - No granular permissions (binary access: allowed or denied)
- Whitelisted IP + valid cert = full API access - Whitelisted IP + valid cert = full API access
### Process Security (systemd Hardening) ### Process Security (Init System Hardening)
- **User:** root (required for package management) - **User:** root (required for package management)
- **NoNewPrivileges:** true (prevent privilege escalation)
- **ProtectSystem:** strict (read-only filesystem except allowed paths)
- **ProtectHome:** true (no access to /home, /root, /run/user)
- **PrivateTmp:** true (isolated /tmp)
- **SystemCallFilter:** Restrict to required syscalls only (application whitelist)
- **RestrictAddressFamilies:** AF_INET, AF_INET6, AF_UNIX (network restrictions)
- **CapabilityBoundingSet:** CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN (minimal capabilities)
**systemd Hardening Options:**
- NoNewPrivileges: true (prevent privilege escalation)
- ProtectSystem: strict (read-only filesystem except allowed paths)
- ProtectHome: true (no access to /home, /root, /run/user)
- PrivateTmp: true (isolated /tmp)
- SystemCallFilter: Restrict to required syscalls only (application whitelist)
**OpenRC Hardening Options:**
- Run as dedicated service user
- File permission restrictions
- chroot isolation (optional)
- Equivalent security via rc.conf and init script options
### Data Security ### Data Security
- All communications encrypted via TLS - All communications encrypted via TLS
- Certificates stored securely with restricted permissions - Certificates stored securely with restricted permissions
@ -149,7 +159,9 @@ The Linux_Patch_API is a secure, single-host API service that enables remote pac
└── audit.log # Local audit log fallback └── audit.log # Local audit log fallback
/usr/bin/linux-patch-api # Binary location /usr/bin/linux-patch-api # Binary location
/etc/systemd/system/linux-patch-api.service # Systemd service Init scripts (distribution-dependent):
- /etc/systemd/system/linux-patch-api.service # systemd
- /etc/init.d/linux-patch-api # OpenRC (Alpine)
``` ```
--- ---

13
Dockerfile.arch Normal file
View File

@ -0,0 +1,13 @@
# Arch Linux container with Node.js for GitHub Actions support
# Used for Arch package builds in CI/CD
FROM archlinux:latest
# Update system and install Node.js (required for GitHub Actions JavaScript-based actions)
RUN pacman -Syu --noconfirm nodejs npm && \
pacman -Scc --noconfirm
# Verify node is available
RUN node --version
# Default command (not used in CI, but good for testing)
CMD ["/bin/bash"]

14
Dockerfile.rpm Normal file
View File

@ -0,0 +1,14 @@
# Fedora container with Node.js for GitHub Actions support
# Used for RPM package builds in CI/CD
FROM fedora:latest
# Install Node.js (required for GitHub Actions JavaScript-based actions)
# Also install dnf-plugins-core for potential multiarch support
RUN dnf install -y nodejs dnf-plugins-core && \
dnf clean all
# Verify node is available
RUN node --version
# Default command (not used in CI, but good for testing)
CMD ["/bin/bash"]

18
SPEC.md
View File

@ -41,7 +41,9 @@
**Primary Objective:** Provide secure API for remote patch/package management on individual Linux hosts **Primary Objective:** Provide secure API for remote patch/package management on individual Linux hosts
**Key Goals:** **Key Goals:**
- Run as systemd service on each managed machine (Option B: Agent Per Host) - Run as a system service on each managed machine (Option B: Agent Per Host)
- systemd for Debian/Ubuntu, RHEL/CentOS/Fedora
- OpenRC for Alpine Linux
- Internal network access only (no internet exposure) - Internal network access only (no internet exposure)
- Support Debian/Ubuntu first, then expand to other distributions - Support Debian/Ubuntu first, then expand to other distributions
- Maintain audit trail of all operations - Maintain audit trail of all operations
@ -55,7 +57,9 @@
- One API instance per host - One API instance per host
- Internal network only (LAN/private network) - Internal network only (LAN/private network)
- No public internet exposure - No public internet exposure
- Must run as systemd service - Must run as a system service (init system determined by distribution)
- systemd: Debian, Ubuntu, RHEL, CentOS, Fedora
- OpenRC: Alpine Linux
**Technical:** **Technical:**
- Must run with elevated privileges for package management (root/sudo) - Must run with elevated privileges for package management (root/sudo)
@ -119,7 +123,9 @@
## Dependencies ## Dependencies
- Linux OS with package manager support - Linux OS with package manager support
- systemd for service management - Init system for service management (distribution-dependent)
- systemd (most distributions)
- OpenRC (Alpine Linux)
- Network access for API communication - Network access for API communication
- mTLS certificate infrastructure (CA, client certs) - mTLS certificate infrastructure (CA, client certs)
- IP whitelist configuration - IP whitelist configuration
@ -147,8 +153,10 @@
- Configuration changes (whitelist updates, cert renewals) - Configuration changes (whitelist updates, cert renewals)
- **Log Storage:** - **Log Storage:**
- Primary: systemd journal (`journalctl`) - Primary: Distribution-appropriate logging
- Secondary: Optional remote syslog server - systemd journal (journalctl) on systemd systems
- syslog/local files on OpenRC systems
- Secondary: Optional remote syslog server (universal)
- Local file logs as fallback (`/var/log/linux_patch_api/`) - Local file logs as fallback (`/var/log/linux_patch_api/`)
- **Log Retention:** - **Log Retention:**

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
# Build Alpine Package (.apk) # Build Alpine Package (.apk)
# Run on: Alpine Linux 3.18+ # Run on: Alpine Linux 3.18+
# Or in Docker: docker run -v $(pwd):/build alpine:latest /build/build-alpine.sh # Or in Docker: docker run -v $(pwd):/build alpine:latest /build/build-alpine.sh
@ -8,12 +8,34 @@ set -e
echo "=== Linux Patch API - Alpine Build Script ===" echo "=== Linux Patch API - Alpine Build Script ==="
echo "" echo ""
# Source cargo environment (for rustup-installed toolchain in CI)
if [ -f "$HOME/.cargo/env" ]; then
. "$HOME/.cargo/env"
fi
# Check if running on Alpine
# Check if running on Alpine
# Check if running on Alpine # Check if running on Alpine
if ! command -v abuild &> /dev/null; then if ! command -v abuild &> /dev/null; then
echo "Installing Alpine build tools..." echo "Installing Alpine build tools..."
apk add --no-cache alpine-sdk rust cargo openssl-dev systemd-dev git apk add --no-cache alpine-sdk rust cargo openssl-dev openrc git
fi fi
# Generate abuild signing keys (ALWAYS generate fresh - same shell session as abuild commands)
echo "Generating abuild signing keys..."
apk add --no-cache abuild
abuild-keygen -a -n 2>&1 | tee /tmp/keygen.log
# Find the actual key file (handles missing username prefix)
KEYFILE=$(ls /root/.abuild/*.rsa 2>/dev/null | head -1)
if [ -z "$KEYFILE" ]; then
KEYFILE=$(ls /root/.abuild/-*.rsa 2>/dev/null | head -1)
fi
echo "Found key: $KEYFILE"
# Write directly to abuild.conf (overwrite any stale config)
echo "PACKAGER_PRIVKEY=\"$KEYFILE\"" > /etc/abuild.conf
cat /etc/abuild.conf
# Setup build environment # Setup build environment
echo "Setting up build environment..." echo "Setting up build environment..."
export CBUILDROOT=$(pwd)/.abuild export CBUILDROOT=$(pwd)/.abuild
@ -27,13 +49,13 @@ cargo build --release --target x86_64-unknown-linux-musl
PKGDIR=$(pwd)/apk-package PKGDIR=$(pwd)/apk-package
mkdir -p "$PKGDIR"/usr/bin mkdir -p "$PKGDIR"/usr/bin
mkdir -p "$PKGDIR"/etc/linux_patch_api mkdir -p "$PKGDIR"/etc/linux_patch_api
mkdir -p "$PKGDIR"/lib/systemd/system mkdir -p "$PKGDIR"/etc/init.d
# Copy files # Copy files
cp target/x86_64-unknown-linux-musl/release/linux-patch-api "$PKGDIR"/usr/bin/ cp target/x86_64-unknown-linux-musl/release/linux-patch-api "$PKGDIR"/usr/bin/
chmod 755 "$PKGDIR"/usr/bin/linux-patch-api chmod 755 "$PKGDIR"/usr/bin/linux-patch-api
cp configs/linux-patch-api.service "$PKGDIR"/lib/systemd/system/ cp configs/linux-patch-api-openrc "$PKGDIR"/etc/init.d/linux-patch-api
cp configs/config.yaml.example "$PKGDIR"/etc/linux_patch_api/config.yaml chmod 755 "$PKGDIR"/etc/init.d/linux-patch-api
cp configs/whitelist.yaml.example "$PKGDIR"/etc/linux_patch_api/whitelist.yaml cp configs/whitelist.yaml.example "$PKGDIR"/etc/linux_patch_api/whitelist.yaml
# Create APKBUILD # Create APKBUILD
@ -46,17 +68,60 @@ pkgdesc="Secure remote package management API for Linux systems"
url="https://gitea.internal/linux-patch-api" url="https://gitea.internal/linux-patch-api"
arch="x86_64" arch="x86_64"
license="MIT" license="MIT"
depends="systemd" makedepends=""
source="apk-package" depends="openrc"
source=""
package() { package() {
cp -r "$srcdir"/apk-package/* "$pkgdir"/ # Create directory structure in pkgdir
install -d "$pkgdir"/usr/bin
install -d "$pkgdir"/etc/linux_patch_api
install -d "$pkgdir"/etc/init.d
# Copy from pre-built apk-package directory
cp -r /workspace/echo/linux_patch_api/apk-package/usr/bin/* "$pkgdir"/usr/bin/
cp -r /workspace/echo/linux_patch_api/apk-package/etc/linux_patch_api/* "$pkgdir"/etc/linux_patch_api/
cp -r /workspace/echo/linux_patch_api/apk-package/etc/init.d/* "$pkgdir"/etc/init.d/
} }
EOF EOF
# Generate checksums for APKBUILD sources
echo "Generating checksums..."
# Build APK package # Build APK package
echo "Building APK package..." echo "Building APK package..."
abuild -F -r
# For CI/container environments where we run as root, create a build user
if [ "$(id -u)" = "0" ]; then
echo "Running as root - creating build user for abuild..."
adduser -D -s /bin/sh builduser 2>/dev/null || true
# CRITICAL: Add builduser to abuild group (required for apk install permissions)
addgroup builduser abuild 2>/dev/null || usermod -aG abuild builduser
chown -R builduser:builduser "$(pwd)"
chown -R builduser:builduser /root/packages 2>/dev/null || true
# Copy abuild keys from root to builduser home
mkdir -p /home/builduser/.abuild
cp /root/.abuild/* /home/builduser/.abuild/
chown -R builduser:builduser /home/builduser/.abuild
# Find the actual key file
KEYFILE=$(ls /home/builduser/.abuild/*.rsa 2>/dev/null | head -1)
if [ -z "$KEYFILE" ]; then
KEYFILE=$(ls /home/builduser/.abuild/-*.rsa 2>/dev/null | head -1)
fi
echo "Key file: $KEYFILE"
echo "Key file exists: $(test -f "$KEYFILE" && echo YES || echo NO)"
# CRITICAL: Write to builduser's PERSONAL abuild.conf (~/.abuild/abuild.conf)
# abuild reads this when running as builduser - standard behavior, no shell quoting issues!
echo "PACKAGER_PRIVKEY=\"$KEYFILE\"" > /home/builduser/.abuild/abuild.conf
chown builduser:builduser /home/builduser/.abuild/abuild.conf
su - builduser -c "cd $(pwd) && abuild checksum && abuild -d -F && cp /home/builduser/packages/x86_64/*.apk ./releases/ 2>/dev/null || cp /home/builduser/packages/*.apk ./releases/ 2>/dev/null || ls -la /home/builduser/packages/"
else
abuild checksum
abuild -F -r
cp ~/packages/x86_64/*.apk releases/ 2>/dev/null || cp ~/packages/*.apk releases/ 2>/dev/null || true
fi
# Copy to releases directory # Copy to releases directory
echo "" echo ""

View File

@ -43,24 +43,34 @@ pkgname=linux-patch-api
pkgver=1.0.0 pkgver=1.0.0
pkgrel=1 pkgrel=1
pkgdesc="Secure remote package management API for Linux systems" pkgdesc="Secure remote package management API for Linux systems"
url="https://gitea.internal/linux-patch-api" url="https://gitea.moon-dragon.us/echo/linux_patch_api"
arch=('x86_64') arch=('x86_64')
license=('MIT') license=('MIT')
depends=('systemd') depends=('systemd')
source=('arch-package')
package() { package() {
cp -r "$srcdir"/arch-package/* "$pkgdir"/ # Use absolute path since makepkg changes working directory to srcdir
cp -r /workspace/echo/linux_patch_api/arch-package/* "$pkgdir"/
} }
EOF EOF
# Create .SRCINFO # Create .SRCINFO
echo "Creating .SRCINFO..." echo "Creating .SRCINFO..."
makepkg --printsrcinfo > .SRCINFO
# Build package # Build package
echo "Building Arch package..." echo "Building Arch package..."
makepkg -f --noconfirm
# For CI/container environments where we run as root, create a build user
if [ "$(id -u)" = "0" ]; then
echo "Running as root - creating build user for makepkg..."
useradd -m builduser 2>/dev/null || true
chown -R builduser:builduser "$(pwd)"
su - builduser -c "cd $(pwd) && makepkg --printsrcinfo > .SRCINFO"
su - builduser -c "cd $(pwd) && makepkg -f --noconfirm"
else
makepkg --printsrcinfo > .SRCINFO
makepkg -f --noconfirm
fi
# Copy to releases directory # Copy to releases directory
echo "" echo ""

View File

@ -0,0 +1,72 @@
#!/sbin/openrc-run
# OpenRC init script for linux-patch-api
# Used on Alpine Linux and other OpenRC-based systems
name="linux_patch_api"
command="/usr/bin/linux-patch-api"
command_args="--config /etc/linux_patch_api/config.yaml"
command_background=true
pidfile="/run/linux-patch-api/linux-patch-api.pid"
output_log="/var/log/linux_patch_api/linux-patch-api.log"
error_log="/var/log/linux_patch_api/linux-patch-api.err"
# Required dependencies
depend() {
use net logger
}
# Create required directories before starting
start_pre() {
checkpath --directory --owner linux-patch-api:linux-patch-api --mode 0755 \
/run/linux-patch-api \
/var/log/linux-patch-api \
/var/lib/linux-patch-api \
/etc/linux_patch_api/certs
# Ensure config files exist
if [ ! -f "/etc/linux_patch_api/config.yaml" ]; then
eerror "Configuration file missing: /etc/linux_patch_api/config.yaml"
eerror "Please create config.yaml before starting the service"
return 1
fi
if [ ! -f "/etc/linux_patch_api/whitelist.yaml" ]; then
eerror "Whitelist file missing: /etc/linux_patch_api/whitelist.yaml"
eerror "Please create whitelist.yaml before starting the service"
return 1
fi
}
# Verify service started successfully
start_post() {
sleep 2
if [ -f "$pidfile" ]; then
einfo "linux-patch-api started successfully (PID: $(cat $pidfile))"
else
ewarn "linux-patch-api may not have started correctly - pidfile not found"
fi
}
# Clean shutdown
stop_pre() {
einfo "Stopping linux-patch-api service..."
}
# Verify service stopped
stop_post() {
if [ -f "$pidfile" ]; then
rm -f "$pidfile"
fi
einfo "linux-patch-api stopped"
}
# Service status
status() {
if [ -f "$pidfile" ] && kill -0 $(cat "$pidfile") 2>/dev/null; then
einfo "linux-patch-api is running (PID: $(cat $pidfile))"
return 0
else
eerror "linux-patch-api is not running"
return 1
fi
}

View File

@ -1,3 +1,5 @@
%global debug_package %{nil}
Name: linux-patch-api Name: linux-patch-api
Version: 1.0.0 Version: 1.0.0
Release: 1%{?dist} Release: 1%{?dist}