From 9500eb2037dc589fc4385587edb7f987ce90e0a4 Mon Sep 17 00:00:00 2001 From: gaelL Date: Wed, 29 May 2019 12:02:14 +0200 Subject: [PATCH] Add new yaml-team-authorized-keys flag to provide authorized team key in one yaml file Fix #3551 Require : https://github.com/concourse/flag/pull/4 Allow users to provide a yaml file containing all team authorized key following this format : ``` - team: teamA ssh_keys: - ssh-rsa keyA - team: teamB ssh_keys: - ssh-rsa keyB ``` Signed-off-by: gaelL --- tsa/tsacmd/command.go | 44 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/tsa/tsacmd/command.go b/tsa/tsacmd/command.go index 1f9218f67..e9841fe2b 100644 --- a/tsa/tsacmd/command.go +++ b/tsa/tsacmd/command.go @@ -8,6 +8,9 @@ import ( "sync" "time" + "io/ioutil" + yaml "gopkg.in/yaml.v2" + "code.cloudfoundry.org/lager" "github.com/concourse/concourse/atc" "github.com/concourse/concourse/tsa" @@ -29,9 +32,10 @@ type TSACommand struct { DebugBindIP flag.IP `long:"debug-bind-ip" default:"127.0.0.1" description:"IP address on which to listen for the pprof debugger endpoints."` DebugBindPort uint16 `long:"debug-bind-port" default:"2221" description:"Port on which to listen for the pprof debugger endpoints."` - HostKey *flag.PrivateKey `long:"host-key" required:"true" description:"Path to private key to use for the SSH server."` - AuthorizedKeys flag.AuthorizedKeys `long:"authorized-keys" description:"Path to file containing keys to authorize, in SSH authorized_keys format (one public key per line)."` - TeamAuthorizedKeys map[string]flag.AuthorizedKeys `long:"team-authorized-keys" value-name:"NAME:PATH" description:"Path to file containing keys to authorize, in SSH authorized_keys format (one public key per line)."` + HostKey *flag.PrivateKey `long:"host-key" required:"true" description:"Path to private key to use for the SSH server."` + AuthorizedKeys flag.AuthorizedKeys `long:"authorized-keys" description:"Path to file containing keys to authorize, in SSH authorized_keys format (one public key per line)."` + TeamAuthorizedKeys map[string]flag.AuthorizedKeys `long:"team-authorized-keys" value-name:"NAME:PATH" description:"Path to file containing keys to authorize, in SSH authorized_keys format (one public key per line)."` + TeamAuthorizedKeysFile flag.File `long:"team-authorized-keys-file" description:"Path to file containing a YAML array of teams and their authorized SSH keys, e.g. [{team:foo,ssh_keys:[key1,key2]}]."` ATCURLs []flag.URL `long:"atc-url" required:"true" description:"ATC API endpoints to which workers will be registered."` @@ -48,6 +52,11 @@ type TeamAuthKeys struct { AuthKeys []ssh.PublicKey } +type yamlTeamAuthorizedKey struct { + Team string `yaml:"team"` + Keys []string `yaml:"ssh_keys,flow"` +} + func (cmd *TSACommand) Execute(args []string) error { runner, err := cmd.Runner(args) if err != nil { @@ -143,6 +152,35 @@ func (cmd *TSACommand) loadTeamAuthorizedKeys() ([]TeamAuthKeys, error) { }) } + // load TeamAuthorizedKeysFile + if cmd.TeamAuthorizedKeysFile != "" { + logger, _ := cmd.constructLogger() + var rawTeamAuthorizedKeys []yamlTeamAuthorizedKey + + authorizedKeysBytes, err := ioutil.ReadFile(cmd.TeamAuthorizedKeysFile.Path()) + if err != nil { + return nil, fmt.Errorf("failed to read yaml authorized keys file: %s", err) + } + err = yaml.Unmarshal([]byte(authorizedKeysBytes), &rawTeamAuthorizedKeys) + if err != nil { + return nil, fmt.Errorf("failed to parse yaml authorized keys file: %s", err) + } + + for _, t := range rawTeamAuthorizedKeys { + var teamAuthorizedKeys []ssh.PublicKey + for _, k := range t.Keys { + key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(k)) + if err != nil { + logger.Error("load-team-authorized-keys-parse", fmt.Errorf("Invalid format, ignoring (%s): %s", k, err.Error())) + continue + } + logger.Info("load-team-authorized-keys-loaded", lager.Data{"team": t.Team, "key": k}) + teamAuthorizedKeys = append(teamAuthorizedKeys, key) + } + teamKeys = append(teamKeys, TeamAuthKeys{Team: t.Team, AuthKeys: teamAuthorizedKeys}) + } + } + return teamKeys, nil }