mirror of
https://github.com/donl/gPanel.git
synced 2026-06-30 06:12:06 -06:00
Merge pull request #142 from george-e-shaw-iv/master
Cleaned up bundle creation process and replaced system package with github.com/george-e-shaw-iv/nixtools
This commit is contained in:
commit
95d39f27bb
17 changed files with 741 additions and 280 deletions
15
Gopkg.lock
generated
15
Gopkg.lock
generated
|
|
@ -13,10 +13,21 @@
|
|||
revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29"
|
||||
version = "v3.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/george-e-shaw-iv/nixtools"
|
||||
packages = ["."]
|
||||
revision = "a3be4bd706b46bc571b4b34981b06089c6c7158d"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["acme","acme/autocert","bcrypt","blowfish"]
|
||||
packages = [
|
||||
"acme",
|
||||
"acme/autocert",
|
||||
"bcrypt",
|
||||
"blowfish"
|
||||
]
|
||||
revision = "2509b142fb2b797aa7587dad548f113b2c0f20ce"
|
||||
|
||||
[[projects]]
|
||||
|
|
@ -28,6 +39,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "bc99bfe3269f7f4c24a0166bbfe5fd0cafdee6c803274787bff0ac01b8cb4ed6"
|
||||
inputs-digest = "95bd56d22992e0d2f4bb1959e7b1b38f5c9716c6c643eff6b6da090d29fb1245"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package system
|
||||
package bundle
|
||||
|
||||
const DEFAULT_INDEX = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/Ennovar/gPanel/pkg/emailer"
|
||||
"github.com/Ennovar/gPanel/pkg/encryption"
|
||||
"github.com/Ennovar/gPanel/pkg/gpaccount"
|
||||
"github.com/Ennovar/gPanel/pkg/system"
|
||||
"github.com/george-e-shaw-iv/nixtools"
|
||||
)
|
||||
|
||||
func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bundles map[string]*gpaccount.Controller) bool {
|
||||
|
|
@ -37,7 +37,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
// Check if account port is in use by system
|
||||
/* Check if account port is in use by system */
|
||||
check, err := net.Listen("tcp", ":"+strconv.Itoa(createBundleRequestData.AccPort))
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + "a service is already listening on port " + strconv.Itoa(createBundleRequestData.AccPort) + "::" + err.Error())
|
||||
|
|
@ -46,7 +46,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
}
|
||||
check.Close()
|
||||
|
||||
// Check if public port is in use by system
|
||||
/* Check if public port is in use by system */
|
||||
check, err = net.Listen("tcp", ":"+strconv.Itoa(createBundleRequestData.PubPort))
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + "a service is already listening on port " + strconv.Itoa(createBundleRequestData.PubPort) + "::" + err.Error())
|
||||
|
|
@ -55,7 +55,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
}
|
||||
check.Close()
|
||||
|
||||
// Check if public/account ports are in use by another bundle
|
||||
/* Check if public/account ports are in use by another bundle */
|
||||
err = nil
|
||||
for k, v := range bundles {
|
||||
if k == createBundleRequestData.Name {
|
||||
|
|
@ -78,11 +78,33 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
//check mail creds exist and work
|
||||
//check admin settings are set
|
||||
//check if can use username
|
||||
//if those pass, then continue with bundle creation
|
||||
/* Check if admin settings are set and valid */
|
||||
ds, err := database.Open("server/" + database.DB_SETTINGS)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
err = ds.CheckAdminSettings()
|
||||
if err != nil {
|
||||
ds.Close()
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
ds.Close()
|
||||
|
||||
/* Check if bundle username can be used within the system */
|
||||
if userExists := nixtools.UserExists(createBundleRequestData.Name); userExists {
|
||||
logger.Println(req.URL.Path + "::username already exists under that bundle name within the system")
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
/* IF ALL CHECKS PASSED, start the bundle creation process */
|
||||
|
||||
/* Create the bundle directory within the gPanel directory */
|
||||
newBundle := "bundles/" + createBundleRequestData.Name
|
||||
err = os.Mkdir(newBundle, 0777)
|
||||
if err != nil {
|
||||
|
|
@ -91,6 +113,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
/* Create the log folder within the new bundle directory */
|
||||
err = os.Mkdir(newBundle+"/logs", 0777)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
|
|
@ -98,13 +121,15 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open(newBundle + "/" + database.DB_MAIN)
|
||||
/* Create and open the newly created bundle's main datastore */
|
||||
ds, err = database.Open(newBundle + "/" + database.DB_MAIN)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Put the new bundle's ports within the datastore */
|
||||
var databaseBundlePorts struct {
|
||||
Account int `json:"account"`
|
||||
Public int `json:"public"`
|
||||
|
|
@ -114,16 +139,19 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
|
||||
err = ds.Put(database.BUCKET_PORTS, []byte("bundle_ports"), databaseBundlePorts)
|
||||
if err != nil {
|
||||
ds.Close()
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Create the default bundle username and password */
|
||||
var defaultBundleUser database.Struct_Users
|
||||
var tempPass = encryption.RandomString(16)
|
||||
|
||||
defaultBundleUser.Pass, err = encryption.HashPassword(tempPass)
|
||||
if err != nil {
|
||||
ds.Close()
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
|
|
@ -133,19 +161,46 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
|
||||
err = ds.Put(database.BUCKET_USERS, []byte("root"), defaultBundleUser)
|
||||
if err != nil {
|
||||
ds.Close()
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
ds.Close()
|
||||
|
||||
err, err2 := system.CreateBundleUser(createBundleRequestData.Name)
|
||||
/* Create a system user for the new bundle */
|
||||
sysUser, err := nixtools.GetUser(createBundleRequestData.Name, true)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error() + " AND " + err2.Error())
|
||||
http.Error(res, err2.Error(), http.StatusInternalServerError)
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Initialize SSH access for the new user and give the root account access */
|
||||
err = sysUser.InitSSH(true)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Create document_root within new system user's home directory */
|
||||
err = sysUser.CreateDirectory("document_root", 0777)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Write the default index within the document_root */
|
||||
err = sysUser.WriteFile("document_root/index.html", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777, []byte(DEFAULT_INDEX))
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Add newly created bundle to list of current bundles (run-time list) */
|
||||
bundles[createBundleRequestData.Name], err = gpaccount.New(newBundle+"/", createBundleRequestData.Name, databaseBundlePorts.Account, databaseBundlePorts.Public)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -154,9 +209,22 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
_ = bundles[createBundleRequestData.Name].Start()
|
||||
_ = bundles[createBundleRequestData.Name].Public.Start()
|
||||
/* Start the account server and public server of the newly created bundle */
|
||||
err = bundles[createBundleRequestData.Name].Start()
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
err = bundles[createBundleRequestData.Name].Public.Start()
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
/* Get SMTP and Admin general settings for use in the email to be sent to new bundle designated email */
|
||||
ds, err = database.Open("server/" + database.DB_SETTINGS)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
|
|
@ -182,6 +250,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
return false
|
||||
}
|
||||
|
||||
/* Send email with information about system and bundle account to designated bundle email AND gPanel admin */
|
||||
mail, err := emailer.New(smtpSettings.Type, emailer.Credentials{
|
||||
Username: smtpSettings.Username,
|
||||
Password: smtpSettings.Password,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
"github.com/Ennovar/gPanel/pkg/gpaccount"
|
||||
"github.com/Ennovar/gPanel/pkg/system"
|
||||
"github.com/george-e-shaw-iv/nixtools"
|
||||
)
|
||||
|
||||
func Delete(res http.ResponseWriter, req *http.Request, logger *log.Logger, bundles map[string]*gpaccount.Controller, dir string) bool {
|
||||
|
|
@ -63,10 +63,17 @@ func Delete(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
|
||||
delete(bundles, rqData.Name)
|
||||
|
||||
err, err2 := system.DeleteBundleUser(rqData.Name)
|
||||
sysUser, err := nixtools.GetUser(rqData.Name, false)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error() + " AND " + err2.Error())
|
||||
http.Error(res, err2.Error(), http.StatusInternalServerError)
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
err = sysUser.Delete(true, false)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/system"
|
||||
"github.com/george-e-shaw-iv/nixtools"
|
||||
)
|
||||
|
||||
func AddKey(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
|
|
@ -28,7 +28,14 @@ func AddKey(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool
|
|||
return false
|
||||
}
|
||||
|
||||
if err = system.AddAuthorizedKey(requestData.Username, requestData.PublicKey); err != nil {
|
||||
sysUser, err := nixtools.GetUser(requestData.Username, false)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = sysUser.AddAuthorizedKey(requestData.PublicKey); err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/system"
|
||||
"github.com/george-e-shaw-iv/nixtools"
|
||||
)
|
||||
|
||||
func DeleteKey(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
|
|
@ -28,7 +28,14 @@ func DeleteKey(res http.ResponseWriter, req *http.Request, logger *log.Logger) b
|
|||
return false
|
||||
}
|
||||
|
||||
if err = system.DeleteAuthorizedKey(requestData.Username, requestData.PublicKey); err != nil {
|
||||
sysUser, err := nixtools.GetUser(requestData.Username, false)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = sysUser.DeleteAuthorizedKey(requestData.PublicKey); err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/system"
|
||||
"github.com/george-e-shaw-iv/nixtools"
|
||||
)
|
||||
|
||||
func GetKeys(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
|
|
@ -27,8 +27,15 @@ func GetKeys(res http.ResponseWriter, req *http.Request, logger *log.Logger) boo
|
|||
return false
|
||||
}
|
||||
|
||||
sysUser, err := nixtools.GetUser(requestData.Username, false)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
var keys []string
|
||||
if keys, err = system.GetAuthorizedKeys(requestData.Username); err != nil {
|
||||
if keys, err = sysUser.GetAuthorizedKeys(true); err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/emailer"
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
type Struct_SMTP struct {
|
||||
Type string `json:"type"`
|
||||
Username string `json:"username"`
|
||||
|
|
@ -9,6 +17,48 @@ type Struct_SMTP struct {
|
|||
}
|
||||
|
||||
type Struct_Admin struct {
|
||||
Name string `json:"name"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
}
|
||||
|
||||
// Function CheckAdminSettings makes sure that the
|
||||
// admin settings are set and are valid.
|
||||
func (ds *Datastore) CheckAdminSettings() (rerr error) {
|
||||
rerr = ds.handle.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(BUCKET_GENERAL))
|
||||
smtp := b.Get([]byte("smtp"))
|
||||
|
||||
var smtpCreds Struct_SMTP
|
||||
err := json.Unmarshal(smtp, &smtpCreds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = emailer.New(smtpCreds.Type, emailer.Credentials{
|
||||
Username: smtpCreds.Username,
|
||||
Password: smtpCreds.Password,
|
||||
Server: smtpCreds.Server,
|
||||
Port: smtpCreds.Port,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a := b.Get([]byte("admin"))
|
||||
|
||||
var admin Struct_Admin
|
||||
err = json.Unmarshal(a, &admin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(admin.Email) == 0 || len(admin.Name) == 0 {
|
||||
return errors.New("admin name and email settings are empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,3 +72,7 @@ func (e *Emailer) SendCustom(to string, msg []byte) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Emailer) Test() {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AddAuthorizedKey(username, key string) error {
|
||||
f, err := os.OpenFile("/home/"+username+"/.ssh/authorized_keys", os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = f.WriteString(key + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteAuthorizedKey(username, key string) error {
|
||||
old, err := ioutil.ReadFile("/home/" + username + "/.ssh/authorized_keys")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(old), "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, key) {
|
||||
lines = append(lines[:i], lines[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
new := strings.Join(lines, "\n")
|
||||
|
||||
f, err := os.OpenFile("/home/"+username+"/.ssh/authorized_keys", os.O_TRUNC|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = f.WriteString(new); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAuthorizedKeys(username string) ([]string, error) {
|
||||
f, err := ioutil.ReadFile("/home/" + username + "/.ssh/authorized_keys")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove empty strings
|
||||
raw := strings.Split(string(f), "\n")
|
||||
var clean []string
|
||||
|
||||
for _, each := range raw {
|
||||
if each != "" {
|
||||
clean = append(clean, each)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove root key
|
||||
if len(clean) == 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return clean[1:], nil
|
||||
}
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func CreateBundleUser(username string) (error, error) {
|
||||
var cerr bytes.Buffer
|
||||
var err error
|
||||
|
||||
adduserArgs := []string{
|
||||
"--disabled-password",
|
||||
"--gecos",
|
||||
"",
|
||||
username,
|
||||
}
|
||||
|
||||
keygenArgs := []string{
|
||||
"-t",
|
||||
"rsa",
|
||||
"-N",
|
||||
"",
|
||||
"-f",
|
||||
"/home/" + username + "/.ssh/id_rsa",
|
||||
}
|
||||
|
||||
// Add the user
|
||||
cmd := exec.Command("adduser", adduserArgs...)
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Create the .ssh folder for said user
|
||||
cmd = exec.Command("mkdir", "/home/"+username+"/.ssh")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Create authorized_keys file
|
||||
cmd = exec.Command("touch", "/home/"+username+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Put root public key into authorized_keys file
|
||||
cmd = exec.Command("cp", "/root/.ssh/id_rsa.pub", "/home/"+username+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Create the host key-pair for said user
|
||||
cmd = exec.Command("ssh-keygen", keygenArgs...)
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Create document root for said user
|
||||
cmd = exec.Command("mkdir", "/home/"+username+"/document_root")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Add default index page
|
||||
f, err := os.OpenFile("/home/"+username+"/document_root/index.html", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fmt.Fprintln(f, DEFAULT_INDEX)
|
||||
|
||||
/* OWNERSHIP AND FILE PERMISSIONS START */
|
||||
cmd = exec.Command("chmod", "700", "/home/"+username+"/.ssh")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "600", "/home/"+username+"/.ssh/id_rsa")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "644", "/home/"+username+"/.ssh/id_rsa.pub")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "644", "/home/"+username+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", username+":", "/home/"+username+"/.ssh")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", username+":", "/home/"+username+"/.ssh/id_rsa")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", username+":", "/home/"+username+"/.ssh/id_rsa.pub")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", username+":", "/home/"+username+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", username+":", "/home/"+username+"/document_root")
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
/* OWNERSHIP AND FILE PERMISSIONS END */
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func DeleteBundleUser(username string) (error, error) {
|
||||
var cerr bytes.Buffer
|
||||
var err error
|
||||
|
||||
// Delete the user and try to remove all files associated
|
||||
cmd := exec.Command("deluser", "--quiet", username)
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
// Forcefully remove the users home directory if it has not already been done
|
||||
// (sometimes deluser doesn't do its job even with the flag)
|
||||
cmd = exec.Command("rm", "-rf", "/home/"+username)
|
||||
cmd.Stderr = &cerr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err, errors.New(cerr.String())
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
21
vendor/github.com/george-e-shaw-iv/nixtools/.github/LICENSE
generated
vendored
Normal file
21
vendor/github.com/george-e-shaw-iv/nixtools/.github/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 George Shaw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
4
vendor/github.com/george-e-shaw-iv/nixtools/.github/README.md
generated
vendored
Normal file
4
vendor/github.com/george-e-shaw-iv/nixtools/.github/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# nixtools
|
||||
A golang toolkit for linux system operations.
|
||||
|
||||
The GoDoc reference for `george-e-shaw-iv/nixtools` is located [here](https://godoc.org/github.com/george-e-shaw-iv/nixtools).
|
||||
16
vendor/github.com/george-e-shaw-iv/nixtools/.gitignore
generated
vendored
Normal file
16
vendor/github.com/george-e-shaw-iv/nixtools/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
nixtools
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
.idea/
|
||||
10
vendor/github.com/george-e-shaw-iv/nixtools/nixtools.go
generated
vendored
Normal file
10
vendor/github.com/george-e-shaw-iv/nixtools/nixtools.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Package nixtools is a toolkit for various linux
|
||||
// system operations.
|
||||
package nixtools
|
||||
|
||||
// Type user is a struct that has functions attached to
|
||||
// it that require a username to properly carry out.
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
}
|
||||
215
vendor/github.com/george-e-shaw-iv/nixtools/ssh.go
generated
vendored
Normal file
215
vendor/github.com/george-e-shaw-iv/nixtools/ssh.go
generated
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
package nixtools
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Function InitSSH creates the necessary folders,
|
||||
// files, and generates a default key-pair for the
|
||||
// given user. If parameter rootHasAccess is set
|
||||
// to true then the public key of the root (sudo) user
|
||||
// will be copied into the authorized_keys file of
|
||||
// the user.
|
||||
func (u *User) InitSSH(rootHasAccess bool) (error) {
|
||||
var stderr bytes.Buffer
|
||||
|
||||
keygenArgs := []string{
|
||||
"-t",
|
||||
"rsa",
|
||||
"-N",
|
||||
"",
|
||||
"-f",
|
||||
"/home/" + u.Name + "/.ssh/id_rsa",
|
||||
}
|
||||
|
||||
// Create the .ssh folder for said user
|
||||
cmd := exec.Command("mkdir", "/home/"+u.Name+"/.ssh")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
// Create authorized_keys file
|
||||
cmd = exec.Command("touch", "/home/"+u.Name+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
if rootHasAccess {
|
||||
// Put root public key into authorized_keys file
|
||||
cmd = exec.Command("cp", "/root/.ssh/id_rsa.pub", "/home/"+u.Name+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Create the default key-pair for said user
|
||||
cmd = exec.Command("ssh-keygen", keygenArgs...)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
/* OWNERSHIP AND FILE PERMISSIONS START */
|
||||
cmd = exec.Command("chmod", "700", "/home/"+u.Name+"/.ssh")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "600", "/home/"+u.Name+"/.ssh/id_rsa")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "644", "/home/"+u.Name+"/.ssh/id_rsa.pub")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chmod", "644", "/home/"+u.Name+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", u.Name+":", "/home/"+u.Name+"/.ssh")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", u.Name+":", "/home/"+u.Name+"/.ssh/id_rsa")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", u.Name+":", "/home/"+u.Name+"/.ssh/id_rsa.pub")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
cmd = exec.Command("chown", u.Name+":", "/home/"+u.Name+"/.ssh/authorized_keys")
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
/* OWNERSHIP AND FILE PERMISSIONS END */
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function AddAuthorizedKey adds a new public key to
|
||||
// a given user's authorized_keys file.
|
||||
func (u *User) AddAuthorizedKey(key string) error {
|
||||
f, err := os.OpenFile("/home/"+u.Name+"/.ssh/authorized_keys", os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = f.WriteString(key + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function DeleteAuthorizedKey removes a public key
|
||||
// that is already in the authorized_keys file of
|
||||
// a given user.
|
||||
func (u *User) DeleteAuthorizedKey(key string) error {
|
||||
old, err := ioutil.ReadFile("/home/" + u.Name + "/.ssh/authorized_keys")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(old), "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, key) {
|
||||
lines = append(lines[:i], lines[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
new := strings.Join(lines, "\n")
|
||||
|
||||
f, err := os.OpenFile("/home/"+u.Name+"/.ssh/authorized_keys", os.O_TRUNC|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = f.WriteString(new); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function GetAuthorizedKeys will return a slice
|
||||
// of strings that contains all of the public keys
|
||||
// within a given user's authorized_keys file.
|
||||
// If the parameter removeRootKey is set to true the
|
||||
// public key of the current root user of the system,
|
||||
// if found within the file, will not be placed within
|
||||
// the slice of strings.
|
||||
func (u *User) GetAuthorizedKeys(removeRootKey bool) ([]string, error) {
|
||||
f, err := ioutil.ReadFile("/home/" + u.Name + "/.ssh/authorized_keys")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove empty strings
|
||||
raw := strings.Split(string(f), "\n")
|
||||
var clean []string
|
||||
|
||||
for _, each := range raw {
|
||||
if each != "" {
|
||||
clean = append(clean, each)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove root key if necessary
|
||||
if removeRootKey {
|
||||
if len(clean) == 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
key, err := ioutil.ReadFile("/root/.ssh/id_rsa.pub")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range clean {
|
||||
if v == string(key) {
|
||||
clean = append(clean[:k], clean[k+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clean, nil
|
||||
}
|
||||
284
vendor/github.com/george-e-shaw-iv/nixtools/users.go
generated
vendored
Normal file
284
vendor/github.com/george-e-shaw-iv/nixtools/users.go
generated
vendored
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
package nixtools
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"bytes"
|
||||
"errors"
|
||||
"strconv"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Function GetUser takes either an ID or Username
|
||||
// as an identifier and returns a type User associated
|
||||
// with the given identifier. createIfNotExist parameter
|
||||
// can only be utilized if the function is given a
|
||||
// username, not an ID.
|
||||
func GetUser(identifier interface{}, createIfNotExist bool) (*User, error) {
|
||||
var u User
|
||||
var err error
|
||||
|
||||
if id, ok := identifier.(int); ok {
|
||||
u.ID = id
|
||||
|
||||
u.Name, err = getUsername(id)
|
||||
if err == nil {
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
} else if name, ok := identifier.(string); ok {
|
||||
u.Name = name
|
||||
|
||||
u.ID, err = getUserID(name)
|
||||
if err == nil {
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
if createIfNotExist {
|
||||
u.ID, err = createUser(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.New("identifier must be a valid user id (int) or username (string)")
|
||||
}
|
||||
|
||||
// Function CreateDirectory attempts to create a directory along
|
||||
// with all of its parent directories (if needed) relative to the
|
||||
// user's home directory. The perm parameter is in the format of linux
|
||||
// file permissions (e.g. 0664).
|
||||
func (u *User) CreateDirectory(dirPath string, perm os.FileMode) (error) {
|
||||
return os.MkdirAll("/home/"+u.Name+"/"+dirPath, perm)
|
||||
}
|
||||
|
||||
// Function WriteFile writes to a file with a given mode that
|
||||
// is set by flags (flag parameter) that are defined within the
|
||||
// os package. The filePath is relative to the current user's
|
||||
// home directory. The perm parameter is in the format of linux
|
||||
// file permissions (e.g. 0664).
|
||||
func (u *User) WriteFile(filePath string, flag int, perm os.FileMode, content []byte) (error) {
|
||||
f, err := os.OpenFile("/home/"+u.Name+"/"+filePath, flag, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
n, err := f.Write(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n != len(content) {
|
||||
f.Close()
|
||||
_ = os.Remove("/home/"+u.Name+"/"+filePath)
|
||||
|
||||
return errors.New("full length of content was not able to be written, file was attempted to be deleted")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function DeleteFileOrDirectory attempts to delete a named
|
||||
// file or directory relative to the user's home directory.
|
||||
func (u *User) DeleteFileOrDirectory(path string) (error) {
|
||||
return os.RemoveAll("/home/"+u.Name+"/"+path)
|
||||
}
|
||||
|
||||
// Function Delete will attempt to delete the given user
|
||||
// attached to the struct. deleteOwnedFiles parameter
|
||||
// will remove all files owned by the user and
|
||||
// removeHome parameter will delete the home directory
|
||||
// of the user. Warning: parameter deleteOwnedFiles will
|
||||
// cause the function to take awhile to execute, consider
|
||||
// using a goroutine to prevent your program from stalling.
|
||||
func (u *User) Delete(removeHome, deleteOwnedFiles bool) (error) {
|
||||
var stderr bytes.Buffer
|
||||
var args = []string{
|
||||
"--quiet",
|
||||
}
|
||||
|
||||
if deleteOwnedFiles {
|
||||
args = append(args, "--remove-all-files")
|
||||
}
|
||||
if removeHome {
|
||||
args = append(args, "--remove-home")
|
||||
}
|
||||
|
||||
args = append(args, u.Name)
|
||||
|
||||
// Delete the user and try to remove all files associated
|
||||
cmd := exec.Command("deluser", args...)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
// Forcefully remove the users home directory as sometimes
|
||||
// the --remove-home or --remove-all-files flags don't work
|
||||
if deleteOwnedFiles || removeHome {
|
||||
cmd = exec.Command("rm", "-rf", "/home/"+u.Name)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function SetPassword sets the users password
|
||||
// to the given parameter.
|
||||
func (u *User) SetPassword(password string) (error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function ForcePasswordChange forces a user to change
|
||||
// their password upon next login.
|
||||
func (u *User) ForcePasswordChange() (error) {
|
||||
cmd := exec.Command("chage", "-d", "0", u.Name)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function Lock lock's a users account, rendering them
|
||||
// unable to login through any means of authentication.
|
||||
func (u *User) Lock() (error) {
|
||||
cmd := exec.Command("chage", "-E", "0", u.Name)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function Unlock will unlock a users account, allowing
|
||||
// them to authenticate through all previous mediums.
|
||||
func (u *User) Unlock() (error) {
|
||||
cmd := exec.Command("chage", "-E", "-1", u.Name)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return errors.New(stderr.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function getUserID returns the ID associated with
|
||||
// a username if it exists or -1 and an error if the
|
||||
// given username does not exist.
|
||||
func getUserID(username string) (int, error) {
|
||||
cmd := exec.Command("id", "-u", username)
|
||||
|
||||
var stderr, stdout bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
cmd.Stdout = &stdout
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return -1, errors.New(stderr.String())
|
||||
}
|
||||
|
||||
stdoutParsed := strings.Replace(stdout.String(), "\n", "", -1)
|
||||
|
||||
id, err := strconv.Atoi(stdoutParsed)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Function getUsername returns the username associated
|
||||
// with an ID if it exists.
|
||||
func getUsername(id int) (string, error) {
|
||||
var stderr, stdout bytes.Buffer
|
||||
reader, writer := io.Pipe()
|
||||
|
||||
cmdOut := exec.Command("getent", "passwd", strconv.Itoa(id))
|
||||
cmdOut.Stdout = writer
|
||||
|
||||
cmdIn := exec.Command("cut", "-d:", "-f1")
|
||||
cmdIn.Stdin = reader
|
||||
cmdIn.Stdout = &stdout
|
||||
cmdIn.Stderr = &stderr
|
||||
|
||||
cmdOut.Start()
|
||||
cmdIn.Start()
|
||||
|
||||
cmdOut.Wait()
|
||||
writer.Close()
|
||||
|
||||
cmdIn.Wait()
|
||||
reader.Close()
|
||||
|
||||
if len(stderr.Bytes()) > 0 {
|
||||
return "", errors.New(stderr.String())
|
||||
}
|
||||
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
// Function userExists returns true if the given
|
||||
// username exists within the system or false if
|
||||
// the given username does not exist.
|
||||
func UserExists(username string) (bool) {
|
||||
cmd := exec.Command("id", "-u", username)
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Function createUser will attempt to create a
|
||||
// new user in the system with the given username.
|
||||
// Upon success will return the new ID of the
|
||||
// created user.
|
||||
func createUser(username string) (int, error) {
|
||||
var stderr bytes.Buffer
|
||||
|
||||
args := []string{
|
||||
"--disabled-password",
|
||||
"--gecos",
|
||||
"",
|
||||
username,
|
||||
}
|
||||
|
||||
cmd := exec.Command("adduser", args...)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return 0, errors.New(stderr.String())
|
||||
}
|
||||
|
||||
id, err := getUserID(username)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue