Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change install log location and restrict permissions #74

Merged
merged 21 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
push:

env:
GOLANGCI_LINT_VERSION: 'v1.46.2'
NFPM_VERSION: 'v2.18.0'
GOLANGCI_LINT_VERSION: 'v1.49.0'
NFPM_VERSION: 'v2.18.1'

jobs:
lint:
Expand Down
2 changes: 1 addition & 1 deletion .nfpm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ contents:
- src: nginx-agent.conf
dst: /etc/nginx-agent/nginx-agent.conf
file_info:
mode: 0660
mode: 0640
- src: ./scripts/packages/nginx-agent.service
dst: /etc/systemd/system/nginx-agent.service
- src: ./scripts/selinux/nginx_agent_selinux.8.gz
Expand Down
2 changes: 1 addition & 1 deletion scripts/.local-nfpm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ contents:
- src: nginx-agent.conf
dst: /etc/nginx-agent/nginx-agent.conf
file_info:
mode: 0660
mode: 0640
- src: ./scripts/packages/nginx-agent.service
dst: /etc/systemd/system/nginx-agent.service
- src: ./scripts/selinux/nginx_agent_selinux.8.gz
Expand Down
2 changes: 1 addition & 1 deletion scripts/docker/alpine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ RUN --mount=type=secret,id=nginx-crt,dst=/etc/apk/cert.pem \
nginx-agent \
" \
&& apk update \
&& apk add $nginxPackages
&& apk add $nginxPackages

# run the nginx and agent
FROM install as runtime
Expand Down
15 changes: 3 additions & 12 deletions scripts/packages/preinstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ INSTANCE_GROUP=""
###### Default variables
################################
export AGENT_GROUP="${AGENT_GROUP:-$(id -ng)}"
export AGENT_INSTALL_LOG="${AGENT_INSTALL_LOG:-/tmp/agent-install.log}"
export AGENT_INSTALL_LOG="${AGENT_INSTALL_LOG:-/var/log/nginx-agent/agent-install-$(date +"%Y-%m-%d-%H.%M.%S").log}"

# Determine OS platform
# shellcheck source=/dev/null
Expand Down Expand Up @@ -50,8 +50,6 @@ AGENT_DYNAMIC_CONFIG_COMMENT="#

"

ALLOWABLE_LOG_LEVELS="trace debug info error fatal panic"

#
# Functions
#
Expand All @@ -77,16 +75,7 @@ ensure_sudo() {
fi
}

is_empty() {
if [ -z "$2" ]; then
printf "\nValue for '%s' blank... skipping" "$1"
return 0
fi
return 1
}

load_config_values() {

# If the file doesn't exist attempt to create it
if [ ! -f "$AGENT_DYNAMIC_CONFIG_FILE" ]; then
printf "Could not find %s ... Creating file\n" ${AGENT_DYNAMIC_CONFIG_FILE}
Expand Down Expand Up @@ -165,3 +154,5 @@ update_config_file() {
load_config_values
update_config_file
} | tee "${AGENT_INSTALL_LOG}"

chmod 0640 "${AGENT_INSTALL_LOG}"
2 changes: 1 addition & 1 deletion src/core/logger/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func SetLogFile(logFile string) *os.File {
logPath = path.Join(logPath, defaultLogFile)
}

logFileHandle, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0664)
logFileHandle, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
if err != nil {
log.Errorf("Failed to set log file, proceeding to log only to stdout/stderr: %v", err)
return nil
Expand Down
194 changes: 90 additions & 104 deletions test/install/agent_install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,128 +4,144 @@ import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const (
osReleasePath = "/etc/os-release"
maxFileSize = int64(20000000)
maxInstallTime = 30 * time.Second
)

var (
AGENT_PACKAGE_FILE = os.Getenv("AGENT_PACKAGE_FILE")
maxFileSize = int64(20000000)
maxInstallTime = 30 * time.Second
expectedLogMsg = LogMessages()
expectedAgentDirs = AgentDirectories()
systemDetails = SystemData()
AGENT_PACKAGE_FILE = os.Getenv("AGENT_PACKAGE_FILE")
installLogFileNameRegexp = regexp.MustCompile("^agent-install-([0-9]+(-[0-9]+)+).[0-9]+.[0-9]+.[log]+")
)

/*
Test Agent Install and Uninstall.
Verifies that agent installs with correct output and files.
Verifies that agent uninstalls and removes all the files.
*/
// TestAgentManualInstallUninstall tests Agent Install and Uninstall.
// Verifies that agent installs with correct output and files.
// Verifies that agent uninstalls and removes all the files.
func TestAgentManualInstallUninstall(t *testing.T) {
expectedLogMsgs := map[string]string{
"ConnectionStatus": "agent_connect_response:<agent_config:<details:<> configs:<configs:<> > > status:<statusCode:CONNECT_OK > >",
"InstallFoundNginxAgent": "Found nginx-agent /usr/bin/nginx-agent",
"InstallAgentToRunAs": "nginx-agent will be configured to run as same user",
"InstallAgentSuccess": "NGINX Agent package has been successfully installed.",
"InstallAgentStartCmd": "sudo systemctl start nginx-agent",
"UninstallAgent": "Removing nginx-agent",
"UninstallAgentStopService": "Stop and disable nginx-agent service",
"UninstallAgentPurgingFiles": "Purging configuration files for nginx-agent",
}

//Set up assertions
checkAgentInstall := assert.New(t)
expectedAgentPaths := map[string]string{
"AgentConfigFile": "/etc/nginx-agent/nginx-agent.conf",
"AgentSystemFile": "/etc/systemd/system/multi-user.target.wants/nginx-agent.service",
"AgentInstallLogDir": "/var/log/nginx-agent/",
}

// Check the environment variable $AGENT_PACKAGE_FILE is set
require.NotEmpty(t, AGENT_PACKAGE_FILE, "Environment variable $AGENT_PACKAGE_FILE not set")

//Check the agent tarball is present
// Check the agent tarball is present
file, err := os.Stat(AGENT_PACKAGE_FILE)
if err != nil {
t.Errorf("Error accessing agent tarball at location: " + AGENT_PACKAGE_FILE)
}
require.NoError(t, err, "Error accessing tarball at: "+AGENT_PACKAGE_FILE)

//Install Agent and record installation time/install output
installTime, agentLog := installAgent(AGENT_PACKAGE_FILE, t)
// Install Agent and record installation time/install output
installTime, agentLog := installAgent(t, AGENT_PACKAGE_FILE)

//Check the file size is less than or equal 20MB
// Check the file size is less than or equal 20MB
assert.LessOrEqual(t, file.Size(), maxFileSize)

//Check the install time under 30s
// Check the install time under 30s
assert.LessOrEqual(t, installTime, float64(maxInstallTime))

//Check install output
checkAgentInstall.Contains(agentLog, expectedLogMsg["InstallFoundNginxAgent"])
checkAgentInstall.Contains(agentLog, expectedLogMsg["InstallAgentToRunAs"])
checkAgentInstall.Contains(agentLog, expectedLogMsg["InstallAgentSuccess"])
checkAgentInstall.Contains(agentLog, expectedLogMsg["InstallAgentStartCmd"])
// Check install output
assert.Contains(t, agentLog, expectedLogMsgs["InstallFoundNginxAgent"])
assert.Contains(t, agentLog, expectedLogMsgs["InstallAgentToRunAs"])
assert.Contains(t, agentLog, expectedLogMsgs["InstallAgentSuccess"])
assert.Contains(t, agentLog, expectedLogMsgs["InstallAgentStartCmd"])

//Check nginx-agent config is created.
_, agentConfigErr := os.Stat(expectedAgentDirs["AgentConfigFile"])
checkAgentInstall.Nil(agentConfigErr)
// Check nginx-agent config is created.
assert.FileExists(t, expectedAgentPaths["AgentConfigFile"])

//Check nginx-agent system unit file is created.
_, agentServiceFile := os.Stat(expectedAgentDirs["AgentSystemFile"])
checkAgentInstall.Nil(agentServiceFile)
// Check nginx-agent system unit file is created.
assert.FileExists(t, expectedAgentPaths["AgentSystemFile"])

//Uninstall the agent package
uninstallLog := uninstallAgent("nginx-agent", t)
// Check nginx-agent install log file is created.
files, err := ioutil.ReadDir(expectedAgentPaths["AgentInstallLogDir"])
require.NoError(t, err)

//Check uninstall output
checkAgentInstall.Contains(uninstallLog, expectedLogMsg["UninstallAgent"])
checkAgentInstall.Contains(uninstallLog, expectedLogMsg["UninstallAgentStopService"])
checkAgentInstall.Contains(uninstallLog, expectedLogMsg["UninstallAgentPurgingFiles"])
installLogFile := ""
for _, f := range files {
if installLogFileNameRegexp.MatchString(f.Name()) {
installLogFile = filepath.Join(expectedAgentPaths["AgentInstallLogDir"], f.Name())
break
}
}
assert.FileExists(t, installLogFile, "agent install log not found")

//Check nginx-agent config is removed.
_, deletedConfigErr := os.Stat(expectedAgentDirs["AgentConfigFile"])
checkAgentInstall.NotNil(deletedConfigErr)
// Uninstall the agent package
uninstallLog := uninstallAgent(t, "nginx-agent")

//Check nginx-agent system unit file is removed.
_, deletedServiceFileError := os.Stat(expectedAgentDirs["AgentSystemFile"])
checkAgentInstall.NotNil(deletedServiceFileError)
}
// Check uninstall output
assert.Contains(t, uninstallLog, expectedLogMsgs["UninstallAgent"])
assert.Contains(t, uninstallLog, expectedLogMsgs["UninstallAgentStopService"])
assert.Contains(t, uninstallLog, expectedLogMsgs["UninstallAgentPurgingFiles"])

// Installs the agent returning total install time and install output
func installAgent(agentPackage string, verify *testing.T) (float64, string) {
// Check nginx-agent config is removed.
assert.NoFileExists(t, expectedAgentPaths["AgentConfigFile"])

//Get OS to create install cmd
installCmd := createInstallCommand(verify)
// Check nginx-agent system unit file is removed.
assert.NoFileExists(t, expectedAgentPaths["AgentSystemFile"])
}

// installAgent installs the agent returning total install time and install output
func installAgent(t *testing.T, agentPackage string) (float64, string) {
// Get OS to create install cmd
installCmd := createInstallCommand(t)

//Start install timer
// Start install timer
start := time.Now()

//Start agent installation and capture install output
// Start agent installation and capture install output
cmd := exec.Command(installCmd[0], installCmd[1], installCmd[2], agentPackage)

stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
verify.Errorf("Error with installation: " + err.Error())
verify.FailNow()
}
require.NoError(t, err)

end := time.Now()
elapsed := end.Sub(start)

return float64(elapsed), string(stdoutStderr)
}

// Uninstall the agent returning output
func uninstallAgent(agentPackage string, verify *testing.T) string {

//Get OS to create uninstall cmd
uninstallCmd := createUninstallCommand(verify)
// uninstallAgent uninstall the agent returning output
func uninstallAgent(t *testing.T, agentPackage string) string {
// Get OS to create uninstall cmd
uninstallCmd := createUninstallCommand(t)

//Start agent uninstall and capture uninstall output
// Start agent uninstall and capture uninstall output
cmd := exec.Command(uninstallCmd[0], uninstallCmd[1], uninstallCmd[2], uninstallCmd[3], agentPackage)

stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
verify.Errorf("Error with uninstall: " + err.Error())
verify.FailNow()
}
require.NoError(t, err)

return string(stdoutStderr)
}

// Creates install command based on OS
func createInstallCommand(t *testing.T) []string {
// Check OS release file exists first to determine OS
require.FileExists(t, osReleasePath)

//Check OS release file exists first to determine OS
_, err := os.Stat(systemDetails["OSReleaseFile"])
if err != nil {
t.Errorf("Error accessing os-release file " + err.Error())
}
content, _ := ioutil.ReadFile(systemDetails["OSReleaseFile"])
content, _ := ioutil.ReadFile(osReleasePath)
os := string(content)
if strings.Contains(os, "UBUNTU") || strings.Contains(os, "Debian") {
return []string{"sudo", "apt", "install"}
Expand All @@ -136,44 +152,14 @@ func createInstallCommand(t *testing.T) []string {

// Creates uninstall command based on OS
func createUninstallCommand(t *testing.T) []string {
// Check OS release file exists first to determine OS
require.FileExists(t, osReleasePath)

//Check OS release file exists first to determine OS
_, err := os.Stat(systemDetails["OSReleaseFile"])
if err != nil {
t.Errorf("Error accessing os-release file " + err.Error())
}
content, _ := ioutil.ReadFile(systemDetails["OSReleaseFile"])
content, _ := ioutil.ReadFile(osReleasePath)
os := string(content)
if strings.Contains(os, "UBUNTU") || strings.Contains(os, "Debian") {
return []string{"sudo", "apt", "purge", "-y"}
} else {
return []string{"sudo", "yum", "remove", "-y"}
}
}

func LogMessages() map[string]string {
return map[string]string{
"ConnectionStatus": "agent_connect_response:<agent_config:<details:<> configs:<configs:<> > > status:<statusCode:CONNECT_OK > >",
"InstallFoundNginxAgent": "Found nginx-agent /usr/bin/nginx-agent",
"InstallAgentToRunAs": "nginx-agent will be configured to run as same user",
"InstallAgentSuccess": "NGINX Agent package has been successfully installed.",
"InstallAgentStartCmd": "sudo systemctl start nginx-agent",
"UninstallAgent": "Removing nginx-agent",
"UninstallAgentStopService": "Stop and disable nginx-agent service",
"UninstallAgentPurgingFiles": "Purging configuration files for nginx-agent",
}
}

func AgentDirectories() map[string]string {
return map[string]string{
"AgentConfigFile": "/etc/nginx-agent/nginx-agent.conf",
"AgentInstallLog": "/tmp/agent-install.log",
"AgentSystemFile": "/etc/systemd/system/multi-user.target.wants/nginx-agent.service",
}
}

func SystemData() map[string]string {
return map[string]string{
"OSReleaseFile": "/etc/os-release",
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.