diff --git a/go.mod b/go.mod index 7c61013..db4dfa7 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module gitlab.com/bboehmke/raspi-alpine-builder go 1.13 -require github.com/stretchr/testify v1.4.0 +require ( + github.com/GehirnInc/crypt v0.0.0-20190301055215-6c0105aabd46 + github.com/stretchr/testify v1.4.0 +) diff --git a/go.sum b/go.sum index a65f495..eb9f130 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,14 @@ +github.com/GehirnInc/crypt v0.0.0-20190301055215-6c0105aabd46 h1:rs0kDBt2zF4/CM9rO5/iH+U22jnTygPlqWgX55Ufcxg= +github.com/GehirnInc/crypt v0.0.0-20190301055215-6c0105aabd46/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/kataras/iris v11.1.1+incompatible/go.mod h1:ki9XPua5SyAJbIxDdsssxevgGrbpBmmvoQmo/A0IodY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/system.go b/system.go new file mode 100644 index 0000000..ca32547 --- /dev/null +++ b/system.go @@ -0,0 +1,84 @@ +package alpine_builder + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "strings" + + "github.com/GehirnInc/crypt" + _ "github.com/GehirnInc/crypt/sha256_crypt" +) + +// system configurations +var systemShadow = "/data/etc/shadow" +var systemDropbearConfig = "/data/etc/dropbear/dropbear.conf" +var systemDropbearRestart = "rc-service dropbear start" +var systemShutdown = "poweroff" +var systemReboot = "reboot" + +// SystemSetRootPassword update shadow file +func SystemSetRootPassword(password string) error { + crypter := crypt.SHA256.New() + + // generate password line + hash, err := crypter.Generate([]byte(password), nil) + if err != nil { + return fmt.Errorf("failed to generate hash: %w", err) + } + line := fmt.Sprintf("root:%s:0:0:::::", hash) + + // write shadow file + return ioutil.WriteFile(systemShadow, []byte(line), os.ModePerm) +} + +// SystemEnableSSH server +func SystemEnableSSH() error { + err := ioutil.WriteFile(systemDropbearConfig, []byte("DROPBEAR_OPTS=\"\""), os.ModePerm) + if err != nil { + return fmt.Errorf("failed to write ssh config: %w", err) + } + + cmdSplit := strings.Split(systemDropbearRestart, " ") + cmd := exec.Command(cmdSplit[0], cmdSplit[1:]...) + err = cmd.Run() + if err != nil { + return fmt.Errorf("failed to restart ssh server: %w", err) + } + return nil +} + +// SystemDisableSSH server +func SystemDisableSSH() error { + err := ioutil.WriteFile(systemDropbearConfig, []byte("DROPBEAR_OPTS=\"-p 127.0.0.1:22\""), os.ModePerm) + if err != nil { + return fmt.Errorf("failed to write ssh config: %w", err) + } + + cmdSplit := strings.Split(systemDropbearRestart, " ") + cmd := exec.Command(cmdSplit[0], cmdSplit[1:]...) + err = cmd.Run() + if err != nil { + return fmt.Errorf("failed to restart ssh server: %w", err) + } + return nil +} + +func SystemShutdown() error { + cmd := exec.Command(systemShutdown) + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to start system shutdown: %w", err) + } + return nil +} + +func SystemReboot() error { + cmd := exec.Command(systemReboot) + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to start system reboot: %w", err) + } + return nil +} diff --git a/system_test.go b/system_test.go new file mode 100644 index 0000000..79b4d64 --- /dev/null +++ b/system_test.go @@ -0,0 +1,75 @@ +package alpine_builder + +import ( + "io/ioutil" + "os" + "strings" + "testing" + + "github.com/GehirnInc/crypt" + _ "github.com/GehirnInc/crypt/sha256_crypt" + "github.com/stretchr/testify/assert" +) + +func init() { + systemShadow = "test_shadow" + systemDropbearConfig = "test_dropbear" + systemDropbearRestart = "restart_dropbear_command" + systemReboot = "reboot_command" + systemShutdown = "shutdown_command" +} + +func TestSystemSetRootPassword(t *testing.T) { + ass := assert.New(t) + + ass.NoError(SystemSetRootPassword("password")) + + data, err := ioutil.ReadFile(systemShadow) + ass.NoError(err) + hash := strings.Split(string(data), ":")[1] + + crypter := crypt.SHA256.New() + ass.NoError(crypter.Verify(hash, []byte("password"))) + + _ = os.Remove(systemShadow) +} + +func TestSystemEnableSSH(t *testing.T) { + ass := assert.New(t) + + ass.EqualError(SystemEnableSSH(), "failed to restart ssh server: exec: \"restart_dropbear_command\": executable file not found in $PATH") + + data, err := ioutil.ReadFile(systemDropbearConfig) + ass.NoError(err) + + ass.Equal("DROPBEAR_OPTS=\"\"", string(data)) + + _ = os.Remove(systemDropbearConfig) +} + +func TestSystemDisableSSH(t *testing.T) { + ass := assert.New(t) + + ass.EqualError(SystemDisableSSH(), "failed to restart ssh server: exec: \"restart_dropbear_command\": executable file not found in $PATH") + + data, err := ioutil.ReadFile(systemDropbearConfig) + ass.NoError(err) + + ass.Equal("DROPBEAR_OPTS=\"-p 127.0.0.1:22\"", string(data)) + + _ = os.Remove(systemDropbearConfig) +} + +func TestSystemReboot(t *testing.T) { + ass := assert.New(t) + + ass.EqualError(SystemReboot(), + "failed to start system reboot: exec: \"reboot_command\": executable file not found in $PATH") +} + +func TestSystemShutdown(t *testing.T) { + ass := assert.New(t) + + ass.EqualError(SystemShutdown(), + "failed to start system shutdown: exec: \"shutdown_command\": executable file not found in $PATH") +}