Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 3503efb

Browse files
committed
Migrated functionality to the keybase bot library
1 parent 232ef8c commit 3503efb

6 files changed

Lines changed: 45 additions & 45 deletions

File tree

‎docker/Makefile‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ build: reset-permissions
1616
# Generate a new CA key
1717
generate: build
1818
source env.sh && docker run -e FORCE_WRITE=$(FORCE_WRITE) -e KEYBASE_USERNAME -e KEYBASE_PAPERKEY -v $(CURDIR)/../example-keybaseca-volume:/mnt:rw ca:latest docker/entrypoint-generate.sh
19-
@echo "In order to make a server accessible via the SSH CA bot, you must now add entries to the correct authorized_keys "
20-
@echo "files. An entry in an authorized keys file lists which Keybase teams are allowed to access it. For example, "
21-
@echo "placing the below line in /home/david/.ssh/authorized_keys would allow people in team.ssh.david_only to log in as david"
22-
@echo ""
23-
@echo "cert-authority,principals=\"team.ssh.david_only\" `cat $(CURDIR)/../example-keybaseca-volume/keybase-ca-key.pub`"
19+
@echo -e "\nRun these commands on each server that you wish to use with the CA chatbot\n"
20+
@echo "useradd user # The user that will be used for non-root logins"
21+
@echo "echo \"`cat $(CURDIR)/../example-keybaseca-volume/keybase-ca-key.pub`\" > /etc/ssh/ca.pub"
22+
@echo "echo \"TrustedUserCAKeys /etc/ssh/ca.pub\" >> /etc/ssh/sshd_config"
23+
@echo "echo \"AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u\" >> /etc/ssh/sshd_config"
24+
@echo "service ssh restart"
25+
@echo -e "\nSee the README for information on how to define which teams are allowed to access which servers"
2426

2527
serve: build
2628
source env.sh && docker run -d --restart unless-stopped -e KEYBASE_USERNAME -e KEYBASE_PAPERKEY -v $(CURDIR)/../example-keybaseca-volume:/mnt:rw ca:latest docker/entrypoint-server.sh

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.12
44

55
require (
66
github.com/google/uuid v1.1.1
7-
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730175146-5efa6a3480b0
7+
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730220753-8e3930228e5a
88
github.com/stretchr/testify v1.3.0
99
github.com/urfave/cli v1.20.0
1010
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4

‎go.sum‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
44
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5-
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730175146-5efa6a3480b0 h1:KxXVvIUAGFbLcfuZ4pM/61qmftaQm03ILpJIOxUO964=
6-
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730175146-5efa6a3480b0/go.mod h1:vNc28YFzigVJod0j5EbuTtRIe7swx8vodh2yA4jZ2s8=
5+
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730220753-8e3930228e5a h1:gZKAzUClAbcGN8rEIUkqG9vXu5g9w+qLD1gA68qOX2Y=
6+
github.com/keybase/go-keybase-chat-bot v0.0.0-20190730220753-8e3930228e5a/go.mod h1:vNc28YFzigVJod0j5EbuTtRIe7swx8vodh2yA4jZ2s8=
77
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
88
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
99
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

‎integrationTest.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ echo "Building containers..."
3232
cd ../docker/ && make && cd ../tests/
3333
docker-compose build
3434
echo "Running integration tests..."
35-
docker-compose up
35+
docker-compose up -d
3636

3737
docker logs kssh -f | indent
3838
TEST_EXIT_CODE=`docker wait kssh`

‎keybaseca/config/config.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func validateChannel(conf Config, teamName string, channelName string) error {
7373
if channel == channelName {
7474
// The channel does exist, but the bot may or may not be in it. So join the channel in order to ensure
7575
// the bot will receive chat events from it
76-
err := api.JoinChannel(teamName, channelName)
76+
_, err := api.JoinChannel(teamName, channelName)
7777
if err != nil {
7878
return fmt.Errorf("failed to join bot to the configured channel: %v", err)
7979
}

‎keybaseca/sshutils/sshutils.go‎

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -120,46 +120,44 @@ func ProcessSignatureRequest(conf config.Config, sr shared.SignatureRequest) (re
120120
return shared.SignatureResponse{SignedKey: string(data), UUID: sr.UUID}, nil
121121
}
122122

123-
// Get the principals that should be placed in the signed certificate
124-
func getPrincipals(conf config.Config, sr shared.SignatureRequest) (string, error) {
125-
// Iterate through the teams in the config file and use the last portion of the subteam as the principal
126-
// if the user is in that subteam
127-
var principals []string
128-
for _, team := range conf.GetTeams() {
129-
members, err := getMembers(conf, team)
130-
if err != nil {
131-
return "", err
132-
}
133-
for _, member := range members {
134-
if member == sr.Username {
135-
principals = append(principals, team)
136-
}
137-
}
138-
}
139-
return strings.Join(principals, ","), nil
140-
}
141-
142-
// Get the members of the given team. Note that this function is a security boundary since if it was bypassed an
123+
// Get the principals that should be placed in the signed certificate.
124+
// Note that this function is a security boundary since if it was bypassed an
143125
// attacker would be able to provision SSH keys for environments that they should not have access to.
144-
func getMembers(conf config.Config, team string) ([]string, error) {
126+
func getPrincipals(conf config.Config, sr shared.SignatureRequest) (string, error) {
127+
// Start by getting the list of teams the user is in
145128
api, err := botwrapper.GetKBChat(conf.GetKeybaseHomeDir(), conf.GetKeybasePaperKey(), conf.GetKeybaseUsername())
146129
if err != nil {
147-
return nil, err
130+
return "", fmt.Errorf("failed to retrieve the list of teams the user is in: %v", err)
148131
}
149-
result, err := api.ListMembersOfTeam(team)
132+
results, err := api.ListUserMemberships(sr.Username)
150133
if err != nil {
151-
return nil, err
152-
}
153-
users := []string{}
154-
for _, member := range result.Owners {
155-
users = append(users, member.Username)
156-
}
157-
for _, member := range result.Admins {
158-
users = append(users, member.Username)
134+
return "", fmt.Errorf("failed to retrieve the list of teams the user is in: %v", err)
135+
}
136+
137+
// Maps from a team to whether or not the user is in the current team (with writer, admin, or owner permissions)
138+
teamToMembership := make(map[string]bool)
139+
for _, result := range results {
140+
// Sadly result.Role is an integer and this is all we're given. Let's hope no one ever changes this enum out
141+
// from underneath us. Admittedly, the worst that could (should) happen is that someone with minimal permissions
142+
// in a team is given access (eg a reader) which wouldn't lead to a complete compromise since an attacker
143+
// would still have to be added as a reader first.
144+
//
145+
// result.Role == 4 --> owner
146+
// result.Role == 3 --> admin
147+
// result.Role == 2 --> writer
148+
if result.Role == 4 || result.Role == 3 || result.Role == 2 {
149+
teamToMembership[result.TeamName] = true
150+
}
159151
}
160-
for _, member := range result.Writers {
161-
users = append(users, member.Username)
152+
153+
// Iterate through the teams in the config file and use the subteam as the principal
154+
// if the user is in that subteam
155+
var principals []string
156+
for _, team := range conf.GetTeams() {
157+
result, ok := teamToMembership[team]
158+
if ok && result {
159+
principals = append(principals, team)
160+
}
162161
}
163-
// Read only users are not listed since they shouldn't be issued SSH keys
164-
return users, nil
162+
return strings.Join(principals, ","), nil
165163
}

0 commit comments

Comments
 (0)