Add SSH Key Management
This commit is contained in:
parent
ef76844922
commit
bcd1805001
62 changed files with 1004 additions and 188 deletions
|
|
@ -148,16 +148,6 @@ func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
context.Println(tpl.AuthorizedKeys)
|
||||
if err := environment.WriteFile(
|
||||
env,
|
||||
tpl.AuthorizedKeys,
|
||||
bootstrap.DefaultAuthorizedKeys,
|
||||
fs.ModePerm,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
context.Println(tpl.SelfResolverBlockFile)
|
||||
if err := environment.WriteFile(
|
||||
env,
|
||||
|
|
|
|||
105
cmd/dis_ssh.go
Normal file
105
cmd/dis_ssh.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// DisSSH is the 'dis_ssh' command
|
||||
var DisSSH wisski_distillery.Command = disSSH{}
|
||||
|
||||
type disSSH struct {
|
||||
Add bool `short:"a" long:"add" description:"add key to user"`
|
||||
Remove bool `short:"r" long:"remove" description:"remove key from user"`
|
||||
Comment string `short:"c" long:"comment" description:"comment of new key"`
|
||||
|
||||
Positionals struct {
|
||||
User string `positional-arg-name:"USER" required:"1-1" description:"distillery username"`
|
||||
Path string `positional-arg-name:"PATH" required:"1-1" description:"Path of key to add"`
|
||||
} `positional-args:"true"`
|
||||
}
|
||||
|
||||
func (disSSH) Description() wisski_distillery.Description {
|
||||
return wisski_distillery.Description{
|
||||
Requirements: cli.Requirements{
|
||||
NeedsDistillery: true,
|
||||
},
|
||||
Command: "dis_ssh",
|
||||
Description: "add or remove an ssh key from a user",
|
||||
}
|
||||
}
|
||||
|
||||
func (ds disSSH) AfterParse() error {
|
||||
var counter int
|
||||
for _, action := range []bool{
|
||||
ds.Add,
|
||||
ds.Remove,
|
||||
} {
|
||||
if action {
|
||||
counter++
|
||||
}
|
||||
}
|
||||
|
||||
if counter != 1 {
|
||||
return errNoActionSelected
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds disSSH) Run(context wisski_distillery.Context) error {
|
||||
switch {
|
||||
case ds.Add:
|
||||
return ds.runAdd(context)
|
||||
case ds.Remove:
|
||||
return ds.runRemove(context)
|
||||
}
|
||||
panic("never reached")
|
||||
}
|
||||
|
||||
var errNoKey = exit.Error{
|
||||
Message: "unable to parse key",
|
||||
ExitCode: exit.ExitCommandArguments,
|
||||
}
|
||||
|
||||
func (ds disSSH) parseOpts(context wisski_distillery.Context) (user *auth.AuthUser, key gossh.PublicKey, err error) {
|
||||
user, err = context.Environment.Auth().User(context.Context, ds.Positionals.User)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
content, err := environment.ReadFile(context.Environment.Environment, ds.Positionals.Path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pk, _, _, _, err := gossh.ParseAuthorizedKey(content)
|
||||
if pk == nil || err != nil {
|
||||
return nil, nil, errNoKey
|
||||
}
|
||||
|
||||
return user, pk, nil
|
||||
}
|
||||
|
||||
func (ds disSSH) runAdd(context wisski_distillery.Context) error {
|
||||
user, key, err := ds.parseOpts(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return context.Environment.Keys().Add(context.Context, user.User.User, ds.Comment, key)
|
||||
}
|
||||
|
||||
func (ds disSSH) runRemove(context wisski_distillery.Context) error {
|
||||
user, key, err := ds.parseOpts(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return context.Environment.Keys().Remove(context.Context, user.User.User, key)
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/cancel"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
)
|
||||
|
|
@ -14,9 +13,9 @@ import (
|
|||
var Server wisski_distillery.Command = server{}
|
||||
|
||||
type server struct {
|
||||
Trigger bool `short:"t" long:"trigger" description:"instead of running on the existing server, simply trigger a cron run"`
|
||||
Prefix string `short:"p" long:"prefix" description:"prefix to listen under"`
|
||||
Bind string `short:"b" long:"bind" description:"address to listen on" default:"127.0.0.1:8888"`
|
||||
Trigger bool `short:"t" long:"trigger" description:"instead of running on the existing server, simply trigger a cron run"`
|
||||
Bind string `short:"b" long:"bind" description:"address to listen on" default:"127.0.0.1:8888"`
|
||||
InternalBind string `short:"i" long:"internal-bind" description:"address to listen on for internal server" default:"127.0.0.1:9999"`
|
||||
}
|
||||
|
||||
func (s server) Description() wisski_distillery.Description {
|
||||
|
|
@ -55,35 +54,54 @@ func (s server) Run(context wisski_distillery.Context) error {
|
|||
}
|
||||
|
||||
// and start the server
|
||||
handler, err := dis.Control().Server(context.Context, context.Stderr)
|
||||
public, internal, err := dis.Control().Server(context.Context, context.Stderr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zerolog.Ctx(context.Context).Info().Str("bind", s.Bind).Msg("listening")
|
||||
// start the public listener
|
||||
publicS := http.Server{Handler: public}
|
||||
publicC := make(chan error)
|
||||
{
|
||||
zerolog.Ctx(context.Context).Info().Str("bind", s.Bind).Msg("listening public server")
|
||||
publicL, err := dis.Still.Environment.Listen("tcp", s.Bind)
|
||||
if err != nil {
|
||||
return errServerListen.Wrap(err)
|
||||
}
|
||||
defer publicS.Shutdown(context.Context)
|
||||
go func() {
|
||||
publicC <- publicS.Serve(publicL)
|
||||
}()
|
||||
}
|
||||
|
||||
// create a new listener
|
||||
listener, err := dis.Still.Environment.Listen("tcp", s.Bind)
|
||||
if err != nil {
|
||||
return errServerListen.Wrap(err)
|
||||
// start the internal listener
|
||||
internalS := http.Server{Handler: internal}
|
||||
internalC := make(chan error)
|
||||
{
|
||||
zerolog.Ctx(context.Context).Info().Str("bind", s.InternalBind).Msg("listening internal server")
|
||||
internalL, err := dis.Still.Environment.Listen("tcp", s.InternalBind)
|
||||
if err != nil {
|
||||
return errServerListen.Wrap(err)
|
||||
}
|
||||
defer internalS.Shutdown(context.Context)
|
||||
go func() {
|
||||
internalC <- internalS.Serve(internalL)
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-context.Context.Done()
|
||||
listener.Close()
|
||||
zerolog.Ctx(context.Context).Info().Msg("shutting down server")
|
||||
publicS.Shutdown(context.Context)
|
||||
internalS.Shutdown(context.Context)
|
||||
}()
|
||||
|
||||
server := http.Server{
|
||||
Handler: http.StripPrefix(s.Prefix, handler),
|
||||
if err2 := <-internalC; err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
if err1 := <-publicC; err1 != nil {
|
||||
err = err1
|
||||
}
|
||||
|
||||
err, _ = cancel.WithContext(context.Context, func(start func()) error {
|
||||
start()
|
||||
return server.Serve(listener)
|
||||
}, func() {
|
||||
zerolog.Ctx(context.Context).Info().Msg("shutting down server")
|
||||
server.Shutdown(context.Context)
|
||||
})
|
||||
|
||||
return errServerListen.Wrap(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ func init() {
|
|||
// distillery auth
|
||||
wdcli.Register(cmd.DisUser)
|
||||
wdcli.Register(cmd.DisGrant)
|
||||
wdcli.Register(cmd.DisSSH)
|
||||
|
||||
// backup & cron
|
||||
wdcli.Register(cmd.Snapshot)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue