Skip to content

Commit

Permalink
Be able to specify team worker without the need of restart Concourse c…
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelL committed Mar 22, 2019
1 parent 059508d commit 4b89114
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/github.com/concourse/flag/authorized_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

type AuthorizedKeys struct {
Keys []ssh.PublicKey
File string
}

func (f *AuthorizedKeys) UnmarshalFlag(value string) error {
Expand All @@ -32,6 +33,12 @@ func (f *AuthorizedKeys) UnmarshalFlag(value string) error {
}

f.Keys = authorizedKeys
f.File = value

return nil
}

// Reload reloads the value of the Keys
func (f *AuthorizedKeys) Reload() error {
return f.UnmarshalFlag(f.File)
}
45 changes: 45 additions & 0 deletions src/github.com/concourse/flag/yaml_team_authorized_keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package flag

import (
"fmt"
"io/ioutil"

"gopkg.in/yaml.v2"
)

//type YamlTeamAuthorizedKeys []struct {
// Team string `yaml:"team"`
// //Keys []ssh.PublicKey `yaml:"ssh_keys,flow"`
// Keys []string `yaml:"ssh_keys,flow"`
//}
type TeamAuthorizedKey struct {
Team string `yaml:"team"`
//Keys []ssh.PublicKey `yaml:"ssh_keys,flow"`
Keys []string `yaml:"ssh_keys,flow"`
}

type YamlTeamAuthorizedKeys struct {
File string
TeamAuthorizedKeys []TeamAuthorizedKey
}

func (f *YamlTeamAuthorizedKeys) UnmarshalFlag(value string) error {
//func (f *YamlTeamAuthorizedKeys) UnmarshalFlag(value string) error {
authorizedKeysBytes, err := ioutil.ReadFile(value)
if err != nil {
return fmt.Errorf("failed to read yaml authorized keys: %s", err)
}

f.File = value

err = yaml.Unmarshal([]byte(authorizedKeysBytes), &f.TeamAuthorizedKeys)
if err != nil {
return fmt.Errorf("failed to parse yaml authorized keys: %s", err)
}

return nil
}

func (f *YamlTeamAuthorizedKeys) Reload() error {
return f.UnmarshalFlag(f.File)
}
12 changes: 9 additions & 3 deletions src/github.com/concourse/tsa/token_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ func (tk *tokenGenerator) GenerateSystemToken() (string, error) {
func (tk *tokenGenerator) GenerateTeamToken(teamName string) (string, error) {
exp := time.Now().Add(time.Hour)
jwtToken := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"exp": exp.Unix(),
"teamName": teamName,
"isAdmin": false,
"exp": exp.Unix(),
"teamName": teamName,
"teams": []string{teamName},
"is_admin": false,
/// Fix generate token to match the key looked in atc/api/accessor/accessor.go TeamNames()
/// This have already been patched in CC version 5.0
/// https://github.com/concourse/atc/commit/ac4b08b719648e3c84ad25a22f421c5c779d0d2f#diff-0d9c12f1c7362814d4f2080cc6e623adR57
/// https://github.com/concourse/concourse/commit/c20d533e0cfd52ee0e8cef4a03d3e99b7fac38af#diff-ad3c8fe4712cc78ba24358cb0c3137d8R38
//"isAdmin": false,
})

return jwtToken.SignedString(tk.signingKey)
Expand Down
69 changes: 68 additions & 1 deletion src/github.com/concourse/tsa/tsacmd/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (

"golang.org/x/crypto/ssh"

"os/signal"
"syscall"

"github.com/concourse/flag"
"github.com/concourse/tsa"
"github.com/concourse/tsa/tsaflags"
Expand All @@ -33,6 +36,7 @@ type TSACommand struct {
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" required:"true" description:"Path to file containing keys to authorize, in SSH authorized_keys format (one public key per line)."`
TeamAuthorizedKeys []tsaflags.InputPairFlag `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)."`
YamlTeamAuthorizedKeys flag.YamlTeamAuthorizedKeys `long:"yaml-team-authorized-keys" description:"Path to file containing keys to authorize, in SSH authorized_keys yaml format."`

ATCURLs []flag.URL `long:"atc-url" required:"true" description:"ATC API endpoints to which workers will be registered."`

Expand Down Expand Up @@ -93,7 +97,6 @@ func (cmd *TSACommand) Runner(args []string) (ifrit.Runner, error) {
}

config, err := cmd.configureSSHServer(sessionAuthTeam, cmd.AuthorizedKeys.Keys, teamAuthorizedKeys)
return nil, fmt.Errorf("FUCKING DEBUG 2 %s", cmd.AuthorizedKeys.Keys)
if err != nil {
return nil, fmt.Errorf("failed to configure SSH server: %s", err)
}
Expand All @@ -119,6 +122,52 @@ func (cmd *TSACommand) Runner(args []string) (ifrit.Runner, error) {
httpClient: http.DefaultClient,
sessionTeam: sessionAuthTeam,
}
// Starts a goroutine that his purpose is to basically listen to the
// SIGUSR1 syscall to then reload the config.
// For now it only reload the TSACommand.AuthorizedKeys but any
// other configuration could be added
go func() {
for {
// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR1)

// Block until a signal is received.
_ = <-c

logger.Info("reloading-config")

err := cmd.AuthorizedKeys.Reload()
if err != nil {
logger.Error("failed to reload the config: %s", err)
continue
}


err = cmd.YamlTeamAuthorizedKeys.Reload()
if err != nil {
logger.Error("failed to reload the team authorized keys : %s", err)
continue
}

teamAuthorizedKeys, err = cmd.loadTeamAuthorizedKeys()
if err != nil {
logger.Error("failed to reload the team authorized keys : %s", err)
continue
}

// compute again the config so it's updated
config, err := cmd.configureSSHServer(sessionAuthTeam, cmd.AuthorizedKeys.Keys, teamAuthorizedKeys)
if err != nil {
logger.Error("failed to configure SSH server: %s", err)
continue
}

server.config = config
}
}()
return serverRunner{logger, server, listenAddr}, nil
}
return nil, fmt.Errorf("missing session signing key")
Expand Down Expand Up @@ -156,6 +205,24 @@ func (cmd *TSACommand) loadTeamAuthorizedKeys() ([]TeamAuthKeys, error) {
teamKeys = append(teamKeys, TeamAuthKeys{Team: cmd.TeamAuthorizedKeys[i].Name, AuthKeys: teamAuthorizedKeys})
}

logger, _ := cmd.constructLogger()
for _, t := range cmd.YamlTeamAuthorizedKeys.TeamAuthorizedKeys {
logger.Info(fmt.Sprintf("Load keys for team : %s", t.Team))
var teamAuthorizedKeys []ssh.PublicKey
for _, k := range t.Keys {
logger.Info(fmt.Sprintf(" - %s", k))
key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(k))
if err != nil {
logger.Error(fmt.Sprintf(" - Invalid format, ignoring %s", k), err)
continue
}

teamAuthorizedKeys = append(teamAuthorizedKeys, key)
}
teamKeys = append(teamKeys, TeamAuthKeys{Team: t.Team, AuthKeys: teamAuthorizedKeys})

}

return teamKeys, nil
}

Expand Down
2 changes: 2 additions & 0 deletions src/github.com/concourse/worker/retire/retire_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type RetireWorkerCommand struct {
TSA tsa.Config `group:"TSA Configuration" namespace:"tsa" required:"true"`

WorkerName string `long:"name" required:"true" description:"The name of the worker you wish to retire."`
WorkerTeam string `long:"team" description:"The team name of the worker you wish to retire."`
}

func (cmd *RetireWorkerCommand) Execute(args []string) error {
Expand All @@ -31,6 +32,7 @@ func (cmd *RetireWorkerCommand) retireWorkerRunner(logger lager.Logger) ifrit.Ru
logger,
atc.Worker{
Name: cmd.WorkerName,
Team: cmd.WorkerTeam,
},
beacon.Config{
TSAConfig: cmd.TSA,
Expand Down

0 comments on commit 4b89114

Please sign in to comment.