Skip to content

Commit e28e3db

Browse files
authored
Merge branch 'cloudfoundry-community:main' into slowdown
2 parents 838099f + 621641e commit e28e3db

File tree

3 files changed

+123
-5
lines changed

3 files changed

+123
-5
lines changed

cf/auth_service.go

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cf
22

33
import (
4+
"encoding/base64"
5+
"encoding/json"
46
"fmt"
57
"net/url"
68
"os"
@@ -11,66 +13,105 @@ import (
1113
"golang.org/x/oauth2"
1214
)
1315

16+
type Logger interface {
17+
Info(tag, message string)
18+
Error(tag, message string)
19+
}
20+
1421
type AuthService struct {
1522
client *cf.Client
23+
logger Logger
1624
}
1725

18-
func NewAuthService(client *cf.Client) *AuthService {
26+
func NewAuthService(client *cf.Client, logger Logger) *AuthService {
1927
return &AuthService{
2028
client: client,
29+
logger: logger,
2130
}
2231
}
2332

2433
func (service *AuthService) Verify(auth string) error {
34+
tag := "AuthService.Verify"
35+
service.logger.Info(tag, "Starting verification process")
2536
username, err := getUsername(auth)
2637
if err != nil {
38+
service.logger.Error(tag, fmt.Sprintf("Error getting username: %v", err))
2739
return err
2840
}
41+
service.logger.Info(tag, fmt.Sprintf("Username obtained: %s", username))
2942

3043
user, err := service.getUser(username)
3144
if err != nil {
45+
service.logger.Error(tag, fmt.Sprintf("Error getting user: %v", err))
3246
return err
3347
}
48+
// Debugging = noisy
49+
// service.logger.Info(tag, fmt.Sprintf("User obtained: %v", user))
3450

3551
roles, err := service.getUserRoles(user)
3652
if err != nil {
53+
service.logger.Error(tag, fmt.Sprintf("Error getting user roles: %v", err))
3754
return err
3855
}
56+
// Debugging = noisy
57+
// service.logger.Info(tag, fmt.Sprintf("User roles obtained: %v", roles))
58+
59+
tokenScopes, err := getTokenScopes(auth, service.logger)
60+
if err != nil {
61+
service.logger.Error(tag, fmt.Sprintf("Error getting token scopes: %v", err))
62+
return err
63+
}
64+
service.logger.Info(tag, fmt.Sprintf("Token scopes obtained: %v", tokenScopes))
3965

4066
// Check all the roles, but return good early if we find one that works.
67+
68+
// Check token scopes for cloud_controller.admin
69+
for _, scope := range tokenScopes {
70+
if scope == "cloud_controller.admin" {
71+
service.logger.Info(tag, "User has cloud_controller.admin scope")
72+
return nil
73+
}
74+
}
75+
76+
// Check CF roles for space_manager or space_developer
4177
for _, role := range roles {
42-
// NOTE: we should definitely be checking space IDs, too, but that's tomorrow
43-
// guy's problem.
4478
if role.Type == "space_manager" || role.Type == "space_developer" {
79+
service.logger.Info(tag, fmt.Sprintf("User has role: %s", role.Type))
4580
return nil
4681
}
4782
}
4883

84+
service.logger.Error(tag, "User does not have sufficient permissions")
4985
return fmt.Errorf("insufficient permissions")
5086
}
5187

5288
func (service *AuthService) getUser(username string) (cf.User, error) {
89+
tag := "AuthService.getUser"
5390
query := url.Values{}
5491
query.Add("username", username)
5592

5693
users, err := service.client.ListUsersByQuery(query)
5794
if err != nil {
95+
service.logger.Error(tag, fmt.Sprintf("Error listing users by query: %v", err))
5896
return cf.User{}, err
5997
}
6098

6199
user := users.GetUserByUsername(username)
62100
if len(user.Guid) == 0 {
101+
service.logger.Error(tag, "No such user found")
63102
return cf.User{}, fmt.Errorf("no such user")
64103
}
65104

66105
return user, nil
67106
}
68107

69108
func (service *AuthService) getUserRoles(user cf.User) ([]cf.V3Role, error) {
109+
tag := "AuthService.getUserRoles"
70110
roleQuery := url.Values{}
71111
roleQuery.Add("user_guids", user.Guid)
72112
roles, err := service.client.ListV3RolesByQuery(roleQuery)
73113
if err != nil {
114+
service.logger.Error(tag, fmt.Sprintf("Error listing V3 roles by query: %v", err))
74115
return nil, err
75116
}
76117

@@ -125,3 +166,48 @@ func getBearer(auth string) (string, error) {
125166

126167
return parts[bearerLoc+1], nil
127168
}
169+
170+
// JWTClaims represents the claims in the JWT token
171+
type JWTClaims struct {
172+
Scope []string `json:"scope"`
173+
}
174+
175+
// DecodeJWT decodes the JWT token and extracts the claims
176+
func DecodeJWT(token string) (*JWTClaims, error) {
177+
parts := strings.Split(token, ".")
178+
if len(parts) < 3 {
179+
return nil, fmt.Errorf("invalid token format")
180+
}
181+
182+
payload := parts[1]
183+
payloadDecoded, err := base64.RawURLEncoding.DecodeString(payload)
184+
if err != nil {
185+
return nil, fmt.Errorf("failed to decode payload: %v", err)
186+
}
187+
188+
var claims JWTClaims
189+
err = json.Unmarshal(payloadDecoded, &claims)
190+
if err != nil {
191+
return nil, fmt.Errorf("failed to unmarshal claims: %v", err)
192+
}
193+
194+
return &claims, nil
195+
}
196+
197+
func getTokenScopes(auth string, logger Logger) ([]string, error) {
198+
tag := "AuthService.getTokenScopes"
199+
bearer, err := getBearer(auth)
200+
if err != nil {
201+
logger.Error(tag, fmt.Sprintf("Error getting bearer token: %v", err))
202+
return nil, err
203+
}
204+
205+
claims, err := DecodeJWT(bearer)
206+
if err != nil {
207+
logger.Error(tag, fmt.Sprintf("Error decoding JWT token: %v", err))
208+
return nil, err
209+
}
210+
211+
logger.Info(tag, fmt.Sprintf("Scopes found in token: %v", claims.Scope))
212+
return claims.Scope, nil
213+
}

cmd/scheduler/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func main() {
102102

103103
log.Info(tag, "got the cf client set up")
104104

105-
auth := cf.NewAuthService(cfclient)
105+
auth := cf.NewAuthService(cfclient, log)
106106
jobs := postgres.NewJobService(db)
107107
calls := postgres.NewCallService(db)
108108
info := cf.NewInfoService(cfclient)

0 commit comments

Comments
 (0)