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

add options to forget command #27

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
70 changes: 70 additions & 0 deletions README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,76 @@ Modify the SSH daemon configuration +/etc/ssh/sshd_config+ by adding:

ForceCommand /usr/sbin/sshproxy

Migrating to sshproxy 2
-----------------------

Version 2 brings a lot of changes to sshproxy:

1. configuration file:
- **all** configuration options can now be set outside of overrides (those are
the default values) or inside an override
- `users`, `groups` and `routes` options have been replaced by the overrides
system:
* old style:

routes:
default:
some_default_options…
service1:
source: [an.ip.sshd.listens.to]
some_sources_options…
users:
- alice,bob:
some_users_options…
groups:
- foo,bar:
some_groups_options…

* new style:

some_default_options…
overrides:
- match:
- sources: [an.ip.sshd.listens.to]
some_sources_options…
- match:
- users: [alice,bob]
some_users_options…
overrides:
- match:
- groups: [foo,bar]
some_groups_options…

- the `match` conditions of the overrides system can be combined. Here is an
example meaning "match if (the user is in the group foo **and** in the
group bar) **or** ((the user is alice **or** bob) **and** the user is
connected to an.ip.sshd.listens.to)":

overrides:
- match:
- groups: [foo]
groups: [bar]
- users: [alice,bob]
sources: [an.ip.sshd.listens.to]

- nodesets can now be used for the `dest` key
- if `libnodeset.so` is found, it allows the use of clustershell groups where
nodesets are allowed
2. command line interface:
- in all the tables, `Host` and `Port` columns are now merged into a single
`Host:Port`
- `sshproxyctl get_config` has been moved to `sshproxyctl show config`
- `sshproxyctl show hosts` and `sshproxyctl show users -all` now display
persist info
- `sshproxyctl enable HOST [PORT]` has been moved to `sshproxyctl enable
-all|-host HOST [-port PORT]`
- `sshproxyctl disable HOST [PORT]` has been moved to `sshproxyctl disable
-all|-host HOST [-port PORT]`
- `sshproxyctl forget HOST [PORT]` has been moved to `sshproxyctl forget host
-all|-host HOST [-port PORT]`
- `sshproxyctl error_banner` (without any parameter) has been moved to
`sshproxyctl forget error_banner`

Copying
-------

Expand Down
198 changes: 137 additions & 61 deletions cmd/sshproxyctl/sshproxyctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ var (
// SshproxyVersion is set by Makefile
SshproxyVersion = "0.0.0+noproperlybuilt"
defaultConfig = "/etc/sshproxy/sshproxy.yaml"
defaultHostPort = "22"
)

func mustInitEtcdClient(configFile string) *utils.Client {
Expand Down Expand Up @@ -536,6 +535,13 @@ func setErrorBanner(errorBanner string, expire time.Time, configFile string) err
return cli.SetErrorBanner(errorBanner, expire)
}

func delErrorBanner(configFile string) error {
cli := mustInitEtcdClient(configFile)
defer cli.Close()

return cli.DelErrorBanner()
}

func showErrorBanner(configFile string) {
cli := mustInitEtcdClient(configFile)
defer cli.Close()
Expand Down Expand Up @@ -592,7 +598,7 @@ The commands are:
version show version number and exit
show show states present in etcd
enable enable a host in etcd
forget forget a host in etcd
forget forget a host/error_banner in etcd
disable disable a host in etcd
error_banner set the error banner in etcd

Expand Down Expand Up @@ -654,39 +660,53 @@ The options are:
return fs
}

func newEnableParser() *flag.FlagSet {
func newEnableParser(allFlag *bool, hostString *string, portString *string) *flag.FlagSet {
fs := flag.NewFlagSet("enable", flag.ExitOnError)
fs.BoolVar(allFlag, "all", false, "enable all hosts present in config")
fs.StringVar(hostString, "host", "", "hostname to enable (can be a nodeset)")
fs.StringVar(portString, "port", "", "port to enable (can be a nodeset)")
fs.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s enable HOST [PORT]
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s enable -all|-host HOST [-port PORT]

Enable a previously disabled host in etcd. The default port is %s. Host and port
can be nodesets.
`, os.Args[0], defaultHostPort)
Enable a previously disabled host in etcd.
`, os.Args[0])
fs.PrintDefaults()
os.Exit(2)
}
return fs
}

func newForgetParser() *flag.FlagSet {
func newForgetParser(allFlag *bool, hostString *string, portString *string) *flag.FlagSet {
fs := flag.NewFlagSet("forget", flag.ExitOnError)
fs.BoolVar(allFlag, "all", false, "forget all hosts present in config")
fs.StringVar(hostString, "host", "", "hostname to forget (can be a nodeset)")
fs.StringVar(portString, "port", "", "port to forget (can be a nodeset)")
fs.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s forget HOST [PORT]
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s forget COMMAND [OPTIONS]

Forget a host in etcd. The default port is %s. Remember that if this host is
used, it will appear back in the list. Host and port can be nodesets.
`, os.Args[0], defaultHostPort)
The cammands are:
host -all|-host HOST [-port PORT] forget a host in etcd
error_banner forget the error_banner in etcd

The options are:
`, os.Args[0])
fs.PrintDefaults()
os.Exit(2)
}
return fs
}

func newDisableParser() *flag.FlagSet {
func newDisableParser(allFlag *bool, hostString *string, portString *string) *flag.FlagSet {
fs := flag.NewFlagSet("disable", flag.ExitOnError)
fs.BoolVar(allFlag, "all", false, "disable all hosts present in config")
fs.StringVar(hostString, "host", "", "hostname to disable (can be a nodeset)")
fs.StringVar(portString, "port", "", "port to disable (can be a nodeset)")
fs.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s disable HOST [PORT]
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s disable -all|-host HOST [-port PORT]

Disable a host in etcd. The default port is %s. Host and port can be nodesets.
`, os.Args[0], defaultHostPort)
Disable a host in etcd.
`, os.Args[0])
fs.PrintDefaults()
os.Exit(2)
}
return fs
Expand All @@ -708,53 +728,73 @@ The options are:
return fs
}

func getHostPortFromCommandLine(args []string) ([]string, []string, error) {
func getHostPortFromCommandLine(allFlag bool, hostsNodeset string, portsNodeset string, configFile string) ([]string, error) {
_, nodesetDlclose, nodesetExpand := nodesets.InitExpander()
defer nodesetDlclose()
hostsNodeset, portsNodeset := "", defaultHostPort
switch len(args) {
case 2:
hostsNodeset, portsNodeset = args[0], args[1]
case 1:
hostsNodeset = args[0]
default:
return []string{}, []string{}, fmt.Errorf("wrong number of arguments")
}

hosts, err := nodesetExpand(hostsNodeset)
configDests, err := utils.LoadAllDestsFromConfig(configFile)
if err != nil {
return []string{}, []string{}, fmt.Errorf("%s", err)
return []string{}, fmt.Errorf("%s", err)
}
ports, err := nodesetExpand(portsNodeset)
if err != nil {
return []string{}, []string{}, fmt.Errorf("%s", err)

if allFlag && portsNodeset == "" {
return configDests, nil
}

var hosts []string
if allFlag {
for _, configDest := range configDests {
host, _, err := utils.SplitHostPort(configDest)
if err != nil {
return []string{}, fmt.Errorf("%s", err)
}
hosts = append(hosts, host)
}
} else {
hosts, err = nodesetExpand(hostsNodeset)
if err != nil {
return []string{}, fmt.Errorf("%s", err)
}
}

var ports []string
if portsNodeset == "" {
for _, configDest := range configDests {
_, port, err := utils.SplitHostPort(configDest)
if err != nil {
return []string{}, fmt.Errorf("%s", err)
}
ports = append(ports, port)
}
} else {
ports, err = nodesetExpand(portsNodeset)
if err != nil {
return []string{}, fmt.Errorf("%s", err)
}
}

var hostPorts []string
for _, port := range ports {
if iport, err := strconv.Atoi(port); err != nil {
return []string{}, []string{}, fmt.Errorf("port \"%s\" must be an integer", port)
return []string{}, fmt.Errorf("port \"%s\" must be an integer", port)
} else if iport < 0 || iport > 65535 {
return []string{}, []string{}, fmt.Errorf("port \"%s\" must be in the 0-65535 range", port)
return []string{}, fmt.Errorf("port \"%s\" must be in the 0-65535 range", port)
}
for _, host := range hosts {
if _, _, err := net.SplitHostPort(host + ":" + port); err != nil {
return []string{}, []string{}, fmt.Errorf("%s", err)
return []string{}, fmt.Errorf("%s", err)
}
hostPorts = append(hostPorts, host+":"+port)
}
}
return hosts, ports, nil
return hostPorts, nil
}

func getErrorBannerFromCommandLine(args []string) (string, error) {
errorBanner := ""
switch len(args) {
case 0:
errorBanner = ""
case 1:
errorBanner = args[0]
default:
return "", fmt.Errorf("wrong number of arguments")
if len(args) == 1 {
return args[0], nil
}
return errorBanner, nil
return "", fmt.Errorf("wrong number of arguments")
}

func byteToHuman(b int, passthrough bool) string {
Expand Down Expand Up @@ -831,14 +871,16 @@ func main() {
var userString string
var groupsString string
var sourceString string
var hostString string
var portString string

parsers := map[string]*flag.FlagSet{
"help": newHelpParser(),
"version": newVersionParser(),
"show": newShowParser(&csvFlag, &jsonFlag, &allFlag, &userString, &groupsString, &sourceString),
"enable": newEnableParser(),
"forget": newForgetParser(),
"disable": newDisableParser(),
"enable": newEnableParser(&allFlag, &hostString, &portString),
"forget": newForgetParser(&allFlag, &hostString, &portString),
"disable": newDisableParser(&allFlag, &hostString, &portString),
"error_banner": newErrorBannerParser(&expire),
}

Expand Down Expand Up @@ -866,7 +908,7 @@ func main() {
p := parsers[cmd]
p.Parse(args)
if p.NArg() == 0 {
fmt.Fprintf(os.Stderr, "ERROR: missing 'hosts' or 'connections'\n\n")
fmt.Fprintf(os.Stderr, "ERROR: missing 'hosts', 'connections', 'users', 'groups', 'error_banner' or 'config'\n\n")
p.Usage()
}
subcmd := p.Arg(0)
Expand All @@ -893,41 +935,75 @@ func main() {
case "enable":
p := parsers[cmd]
p.Parse(args)
hosts, ports, err := getHostPortFromCommandLine(p.Args())
if !allFlag && hostString == "" {
fmt.Fprintf(os.Stderr, "ERROR: missing '-all' or '-host'\n\n")
p.Usage()
}
hostPorts, err := getHostPortFromCommandLine(allFlag, hostString, portString, *configFile)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
for _, host := range hosts {
for _, port := range ports {
enableHost(host, port, *configFile)
for _, hostPort := range hostPorts {
host, port, err := utils.SplitHostPort(hostPort)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
enableHost(host, port, *configFile)
}
case "forget":
p := parsers[cmd]
p.Parse(args)
hosts, ports, err := getHostPortFromCommandLine(p.Args())
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
if p.NArg() == 0 {
fmt.Fprintf(os.Stderr, "ERROR: missing 'host' or 'error_banner'\n\n")
p.Usage()
}
for _, host := range hosts {
for _, port := range ports {
subcmd := p.Arg(0)
// parse flags after subcommand
args = p.Args()[1:]
p.Parse(args)
switch subcmd {
case "host":
if !allFlag && hostString == "" {
fmt.Fprintf(os.Stderr, "ERROR: missing '-all' or '-host'\n\n")
p.Usage()
}
hostPorts, err := getHostPortFromCommandLine(allFlag, hostString, portString, *configFile)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
for _, hostPort := range hostPorts {
host, port, err := utils.SplitHostPort(hostPort)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
forgetHost(host, port, *configFile)
}
case "error_banner":
delErrorBanner(*configFile)
}
case "disable":
p := parsers[cmd]
p.Parse(args)
hosts, ports, err := getHostPortFromCommandLine(p.Args())
if !allFlag && hostString == "" {
fmt.Fprintf(os.Stderr, "ERROR: missing '-all' or '-host'\n\n")
p.Usage()
}
hostPorts, err := getHostPortFromCommandLine(allFlag, hostString, portString, *configFile)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
for _, host := range hosts {
for _, port := range ports {
disableHost(host, port, *configFile)
for _, hostPort := range hostPorts {
host, port, err := utils.SplitHostPort(hostPort)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
p.Usage()
}
disableHost(host, port, *configFile)
}
case "error_banner":
p := parsers[cmd]
Expand Down
Loading