Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ jobs:
cache: true
- name: build application
run: make build-cross-platform
- name: package nodeadm binaries
run: |
mkdir -p dist
tar -C _bin/amd64 -czf dist/nodeadm-linux-amd64.tar.gz nodeadm
tar -C _bin/arm64 -czf dist/nodeadm-linux-arm64.tar.gz nodeadm
sha256sum dist/nodeadm-linux-amd64.tar.gz > dist/nodeadm-linux-amd64.tar.gz.sha256
sha256sum dist/nodeadm-linux-arm64.tar.gz > dist/nodeadm-linux-arm64.tar.gz.sha256
- name: upload nodeadm artifacts
uses: actions/upload-artifact@v4
with:
name: nodeadm-linux-binaries-${{ github.sha }}
path: |
dist/nodeadm-linux-amd64.tar.gz
dist/nodeadm-linux-amd64.tar.gz.sha256
dist/nodeadm-linux-arm64.tar.gz
dist/nodeadm-linux-arm64.tar.gz.sha256
retention-days: 14
test:
name: unit-test
runs-on: ubuntu-latest
Expand Down
13 changes: 12 additions & 1 deletion internal/network/proxy_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ func validateSSMProxyConfig(osName string) error {
var ssmServicePath string
switch osName {
case system.UbuntuOsName:
ssmServicePath = "/etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d/http-proxy.conf"
if isSnapSSMInstall() {
ssmServicePath = "/etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d/http-proxy.conf"
} else {
ssmServicePath = "/etc/systemd/system/amazon-ssm-agent.service.d/http-proxy.conf"
}
case system.RhelOsName, system.AmazonOsName:
ssmServicePath = "/etc/systemd/system/amazon-ssm-agent.service.d/http-proxy.conf"
default:
Expand All @@ -189,6 +193,13 @@ func validateSSMProxyConfig(osName string) error {
return validateSystemdServiceProxyConfig("SSM", ssmServicePath)
}

const snapSSMAgentBinaryPath = "/snap/amazon-ssm-agent/current/amazon-ssm-agent"

func isSnapSSMInstall() bool {
_, err := os.Stat(snapSSMAgentBinaryPath)
return !os.IsNotExist(err)
}

// validateAptProxyConfig validates the apt proxy configuration
func validateAptProxyConfig(httpProxy, httpsProxy string) error {
aptConfPath := "/etc/apt/apt.conf.d/proxy.conf"
Expand Down
15 changes: 11 additions & 4 deletions internal/packagemanager/packagemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,11 @@ func (pm *DistroPackageManager) GetIptables() artifact.Package {
)
}

// GetSSMPackage satisfies the getssmpackage source interface
// GetSSMPackage satisfies the getssmpackage source interface.
// On apt-based systems (Ubuntu), SSM may be installed via snap or via deb.
// We check for the snap binary to determine which package manager to use.
func (pm *DistroPackageManager) GetSSMPackage() artifact.Package {
// SSM is installed using snap package manager. If apt package manager
// is detected, use snap to install/uninstall SSM.
if pm.manager == aptPackageManager {
if pm.manager == aptPackageManager && isSnapSSMInstall() {
return artifact.NewPackageSource(
artifact.NewCmd(snapPackageManager, snapInstallVerb, ssmPkgName),
artifact.NewCmd(snapPackageManager, snapRemoveVerb, ssmPkgName),
Expand All @@ -263,6 +263,13 @@ func (pm *DistroPackageManager) GetSSMPackage() artifact.Package {
)
}

const snapSSMAgentBinaryPath = "/snap/amazon-ssm-agent/current/amazon-ssm-agent"

func isSnapSSMInstall() bool {
_, err := os.Stat(snapSSMAgentBinaryPath)
return !os.IsNotExist(err)
}

func (pm *DistroPackageManager) caCertsPackage() artifact.Package {
return artifact.NewPackageSource(
artifact.NewCmd(pm.manager, pm.installVerb, caCertsPkgName, "-y"),
Expand Down
2 changes: 1 addition & 1 deletion internal/ssm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (s *ssm) registerMachine(ctx context.Context, cfg *api.NodeConfig) error {

var possibleAgentPaths = []string{
"/usr/bin/amazon-ssm-agent",
"/snap/amazon-ssm-agent/current/amazon-ssm-agent",
snapAgentBinaryPath,
}

func agentBinaryPath() (string, error) {
Expand Down
29 changes: 21 additions & 8 deletions internal/ssm/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const (
awsCredentialsFilePath = defaultAWSConfigPath + "/credentials"
eksHybridPath = "/eks-hybrid"
symlinkedAWSConfigPath = eksHybridPath + "/.aws"

snapAgentBinaryPath = "/snap/amazon-ssm-agent/current/amazon-ssm-agent"
snapSsmDaemonName = "snap.amazon-ssm-agent.amazon-ssm-agent"
defaultSsmDaemonName = "amazon-ssm-agent"
)

type ssm struct {
Expand Down Expand Up @@ -119,13 +123,22 @@ func (s *ssm) Name() string {
}

func setDaemonName() {
osToDaemonName := map[string]string{
system.UbuntuOsName: "snap.amazon-ssm-agent.amazon-ssm-agent",
system.RhelOsName: "amazon-ssm-agent",
system.AmazonOsName: "amazon-ssm-agent",
}
osName := system.GetOsName()
if daemonName, ok := osToDaemonName[osName]; ok {
SsmDaemonName = daemonName
SsmDaemonName = resolveDaemonName(system.GetOsName(), fileExists)
}

// resolveDaemonName determines the correct SSM daemon name based on the OS and
// how the agent was installed. On Ubuntu, SSM can be installed via snap or deb;
// this function checks for the snap binary to distinguish between the two.
func resolveDaemonName(osName string, exists func(string) bool) string {
switch osName {
case system.UbuntuOsName:
if exists(snapAgentBinaryPath) {
return snapSsmDaemonName
}
return defaultSsmDaemonName
case system.RhelOsName, system.AmazonOsName:
return defaultSsmDaemonName
default:
return defaultSsmDaemonName
}
}
65 changes: 65 additions & 0 deletions internal/ssm/daemon_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package ssm

import (
"testing"

"github.com/aws/eks-hybrid/internal/system"
)

func TestResolveDaemonName(t *testing.T) {
tests := []struct {
name string
osName string
snapExists bool
expectedName string
}{
{
name: "ubuntu with snap install",
osName: system.UbuntuOsName,
snapExists: true,
expectedName: snapSsmDaemonName,
},
{
name: "ubuntu with deb install",
osName: system.UbuntuOsName,
snapExists: false,
expectedName: defaultSsmDaemonName,
},
{
name: "rhel",
osName: system.RhelOsName,
snapExists: false,
expectedName: defaultSsmDaemonName,
},
{
name: "amazon linux",
osName: system.AmazonOsName,
snapExists: false,
expectedName: defaultSsmDaemonName,
},
{
name: "unknown os",
osName: "unknown",
snapExists: false,
expectedName: defaultSsmDaemonName,
},
{
name: "empty os name",
osName: "",
snapExists: false,
expectedName: defaultSsmDaemonName,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
exists := func(path string) bool {
return tt.snapExists && path == snapAgentBinaryPath
}
got := resolveDaemonName(tt.osName, exists)
if got != tt.expectedName {
t.Errorf("resolveDaemonName(%q) = %q, want %q", tt.osName, got, tt.expectedName)
}
})
}
}
Loading