Skip to content

Commit 0da7dd4

Browse files
committed
ccm,ocm: eliminate legacy mode, convert to multi-credential at init
1 parent 13f6e87 commit 0da7dd4

8 files changed

Lines changed: 118 additions & 108 deletions

File tree

service/ccm/credential_builder.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,18 @@ func validateCCMOptions(options option.CCMServiceOptions) error {
159159
func credentialForUser(
160160
userConfigMap map[string]*option.CCMUser,
161161
providers map[string]credentialProvider,
162-
legacyProvider credentialProvider,
163162
username string,
164163
) (credentialProvider, error) {
165-
if legacyProvider != nil {
166-
return legacyProvider, nil
167-
}
168164
userConfig, exists := userConfigMap[username]
169165
if !exists {
170166
return nil, E.New("no credential mapping for user: ", username)
171167
}
168+
if userConfig.Credential == "" {
169+
for _, provider := range providers {
170+
return provider, nil
171+
}
172+
return nil, E.New("no credential available")
173+
}
172174
provider, exists := providers[userConfig.Credential]
173175
if !exists {
174176
return nil, E.New("unknown credential: ", userConfig.Credential)
@@ -178,15 +180,14 @@ func credentialForUser(
178180

179181
func noUserCredentialProvider(
180182
providers map[string]credentialProvider,
181-
legacyProvider credentialProvider,
182183
options option.CCMServiceOptions,
183184
) credentialProvider {
184-
if legacyProvider != nil {
185-
return legacyProvider
186-
}
187185
if len(options.Credentials) > 0 {
188186
tag := options.Credentials[0].Tag
189187
return providers[tag]
190188
}
189+
for _, provider := range providers {
190+
return provider
191+
}
191192
return nil
192193
}

service/ccm/service.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,6 @@ type Service struct {
161161
trackingGroup sync.WaitGroup
162162
shuttingDown bool
163163

164-
// Legacy mode (single credential)
165-
legacyCredential *defaultCredential
166-
legacyProvider credentialProvider
167-
168-
// Multi-credential mode
169164
providers map[string]credentialProvider
170165
allCredentials []Credential
171166
userConfigMap map[string]*option.CCMUser
@@ -220,9 +215,17 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
220215
if err != nil {
221216
return nil, err
222217
}
223-
service.legacyCredential = credential
224-
service.legacyProvider = &singleCredentialProvider{credential: credential}
218+
service.providers = map[string]credentialProvider{
219+
"default": &singleCredentialProvider{credential: credential},
220+
}
225221
service.allCredentials = []Credential{credential}
222+
if len(options.Users) > 0 {
223+
userConfigMap := make(map[string]*option.CCMUser)
224+
for i := range options.Users {
225+
userConfigMap[options.Users[i].Name] = &options.Users[i]
226+
}
227+
service.userConfigMap = userConfigMap
228+
}
226229
}
227230

228231
if options.TLS != nil {

service/ccm/service_handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,14 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
168168
if len(s.options.Users) > 0 {
169169
userConfig = s.userConfigMap[username]
170170
var err error
171-
provider, err = credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, username)
171+
provider, err = credentialForUser(s.userConfigMap, s.providers, username)
172172
if err != nil {
173173
s.logger.ErrorContext(ctx, "resolve credential: ", err)
174174
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
175175
return
176176
}
177177
} else {
178-
provider = noUserCredentialProvider(s.providers, s.legacyProvider, s.options)
178+
provider = noUserCredentialProvider(s.providers, s.options)
179179
}
180180
if provider == nil {
181181
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "no credential available")

service/ccm/service_status.go

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,43 @@ func (s *Service) handleStatusEndpoint(w http.ResponseWriter, r *http.Request) {
1515
return
1616
}
1717

18-
if len(s.options.Users) == 0 {
19-
writeJSONError(w, r, http.StatusForbidden, "authentication_error", "status endpoint requires user authentication")
20-
return
21-
}
22-
23-
if r.Header.Get("X-Api-Key") != "" || r.Header.Get("Api-Key") != "" {
24-
writeJSONError(w, r, http.StatusBadRequest, "invalid_request_error",
25-
"API key authentication is not supported; use Authorization: Bearer with a CCM user token")
26-
return
27-
}
18+
var provider credentialProvider
19+
var userConfig *option.CCMUser
20+
if len(s.options.Users) > 0 {
21+
if r.Header.Get("X-Api-Key") != "" || r.Header.Get("Api-Key") != "" {
22+
writeJSONError(w, r, http.StatusBadRequest, "invalid_request_error",
23+
"API key authentication is not supported; use Authorization: Bearer with a CCM user token")
24+
return
25+
}
2826

29-
authHeader := r.Header.Get("Authorization")
30-
if authHeader == "" {
31-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "missing api key")
32-
return
33-
}
34-
clientToken := strings.TrimPrefix(authHeader, "Bearer ")
35-
if clientToken == authHeader {
36-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key format")
37-
return
38-
}
39-
username, ok := s.userManager.Authenticate(clientToken)
40-
if !ok {
41-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key")
42-
return
43-
}
27+
authHeader := r.Header.Get("Authorization")
28+
if authHeader == "" {
29+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "missing api key")
30+
return
31+
}
32+
clientToken := strings.TrimPrefix(authHeader, "Bearer ")
33+
if clientToken == authHeader {
34+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key format")
35+
return
36+
}
37+
username, ok := s.userManager.Authenticate(clientToken)
38+
if !ok {
39+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key")
40+
return
41+
}
4442

45-
userConfig := s.userConfigMap[username]
46-
if userConfig == nil {
47-
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "user config not found")
48-
return
43+
userConfig = s.userConfigMap[username]
44+
var err error
45+
provider, err = credentialForUser(s.userConfigMap, s.providers, username)
46+
if err != nil {
47+
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
48+
return
49+
}
50+
} else {
51+
provider = noUserCredentialProvider(s.providers, s.options)
4952
}
50-
51-
provider, err := credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, username)
52-
if err != nil {
53-
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
53+
if provider == nil {
54+
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "no credential available")
5455
return
5556
}
5657

@@ -72,10 +73,10 @@ func (s *Service) computeAggregatedUtilization(provider credentialProvider, user
7273
if !credential.isAvailable() {
7374
continue
7475
}
75-
if userConfig.ExternalCredential != "" && credential.tagName() == userConfig.ExternalCredential {
76+
if userConfig != nil && userConfig.ExternalCredential != "" && credential.tagName() == userConfig.ExternalCredential {
7677
continue
7778
}
78-
if !userConfig.AllowExternalUsage && credential.isExternal() {
79+
if userConfig != nil && !userConfig.AllowExternalUsage && credential.isExternal() {
7980
continue
8081
}
8182
weight := credential.planWeight()
@@ -100,7 +101,7 @@ func (s *Service) computeAggregatedUtilization(provider credentialProvider, user
100101
}
101102

102103
func (s *Service) rewriteResponseHeadersForExternalUser(headers http.Header, userConfig *option.CCMUser) {
103-
provider, err := credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, userConfig.Name)
104+
provider, err := credentialForUser(s.userConfigMap, s.providers, userConfig.Name)
104105
if err != nil {
105106
return
106107
}

service/ocm/credential_builder.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,18 @@ func validateOCMCompositeCredentialModes(
190190
func credentialForUser(
191191
userConfigMap map[string]*option.OCMUser,
192192
providers map[string]credentialProvider,
193-
legacyProvider credentialProvider,
194193
username string,
195194
) (credentialProvider, error) {
196-
if legacyProvider != nil {
197-
return legacyProvider, nil
198-
}
199195
userConfig, exists := userConfigMap[username]
200196
if !exists {
201197
return nil, E.New("no credential mapping for user: ", username)
202198
}
199+
if userConfig.Credential == "" {
200+
for _, provider := range providers {
201+
return provider, nil
202+
}
203+
return nil, E.New("no credential available")
204+
}
203205
provider, exists := providers[userConfig.Credential]
204206
if !exists {
205207
return nil, E.New("unknown credential: ", userConfig.Credential)
@@ -209,15 +211,14 @@ func credentialForUser(
209211

210212
func noUserCredentialProvider(
211213
providers map[string]credentialProvider,
212-
legacyProvider credentialProvider,
213214
options option.OCMServiceOptions,
214215
) credentialProvider {
215-
if legacyProvider != nil {
216-
return legacyProvider
217-
}
218216
if len(options.Credentials) > 0 {
219217
tag := options.Credentials[0].Tag
220218
return providers[tag]
221219
}
220+
for _, provider := range providers {
221+
return provider
222+
}
222223
return nil
223224
}

service/ocm/service.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,6 @@ type Service struct {
176176
webSocketConns map[*webSocketSession]struct{}
177177
shuttingDown bool
178178

179-
// Legacy mode
180-
legacyCredential *defaultCredential
181-
legacyProvider credentialProvider
182-
183-
// Multi-credential mode
184179
providers map[string]credentialProvider
185180
allCredentials []Credential
186181
userConfigMap map[string]*option.OCMUser
@@ -234,9 +229,17 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
234229
if err != nil {
235230
return nil, err
236231
}
237-
service.legacyCredential = credential
238-
service.legacyProvider = &singleCredentialProvider{credential: credential}
232+
service.providers = map[string]credentialProvider{
233+
"default": &singleCredentialProvider{credential: credential},
234+
}
239235
service.allCredentials = []Credential{credential}
236+
if len(options.Users) > 0 {
237+
userConfigMap := make(map[string]*option.OCMUser)
238+
for i := range options.Users {
239+
userConfigMap[options.Users[i].Name] = &options.Users[i]
240+
}
241+
service.userConfigMap = userConfigMap
242+
}
240243
}
241244

242245
if options.TLS != nil {

service/ocm/service_handler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ func extractWeeklyCycleHint(headers http.Header) *WeeklyCycleHint {
5353

5454
func (s *Service) resolveCredentialProvider(username string) (credentialProvider, error) {
5555
if len(s.options.Users) > 0 {
56-
return credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, username)
56+
return credentialForUser(s.userConfigMap, s.providers, username)
5757
}
58-
provider := noUserCredentialProvider(s.providers, s.legacyProvider, s.options)
58+
provider := noUserCredentialProvider(s.providers, s.options)
5959
if provider == nil {
6060
return nil, E.New("no credential available")
6161
}
@@ -117,14 +117,14 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
117117
if len(s.options.Users) > 0 {
118118
userConfig = s.userConfigMap[username]
119119
var err error
120-
provider, err = credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, username)
120+
provider, err = credentialForUser(s.userConfigMap, s.providers, username)
121121
if err != nil {
122122
s.logger.ErrorContext(ctx, "resolve credential: ", err)
123123
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
124124
return
125125
}
126126
} else {
127-
provider = noUserCredentialProvider(s.providers, s.legacyProvider, s.options)
127+
provider = noUserCredentialProvider(s.providers, s.options)
128128
}
129129
if provider == nil {
130130
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "no credential available")

service/ocm/service_status.go

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,43 @@ func (s *Service) handleStatusEndpoint(w http.ResponseWriter, r *http.Request) {
1515
return
1616
}
1717

18-
if len(s.options.Users) == 0 {
19-
writeJSONError(w, r, http.StatusForbidden, "authentication_error", "status endpoint requires user authentication")
20-
return
21-
}
22-
23-
if r.Header.Get("X-Api-Key") != "" || r.Header.Get("Api-Key") != "" {
24-
writeJSONError(w, r, http.StatusBadRequest, "invalid_request_error",
25-
"API key authentication is not supported; use Authorization: Bearer with an OCM user token")
26-
return
27-
}
18+
var provider credentialProvider
19+
var userConfig *option.OCMUser
20+
if len(s.options.Users) > 0 {
21+
if r.Header.Get("X-Api-Key") != "" || r.Header.Get("Api-Key") != "" {
22+
writeJSONError(w, r, http.StatusBadRequest, "invalid_request_error",
23+
"API key authentication is not supported; use Authorization: Bearer with an OCM user token")
24+
return
25+
}
2826

29-
authHeader := r.Header.Get("Authorization")
30-
if authHeader == "" {
31-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "missing api key")
32-
return
33-
}
34-
clientToken := strings.TrimPrefix(authHeader, "Bearer ")
35-
if clientToken == authHeader {
36-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key format")
37-
return
38-
}
39-
username, ok := s.userManager.Authenticate(clientToken)
40-
if !ok {
41-
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key")
42-
return
43-
}
27+
authHeader := r.Header.Get("Authorization")
28+
if authHeader == "" {
29+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "missing api key")
30+
return
31+
}
32+
clientToken := strings.TrimPrefix(authHeader, "Bearer ")
33+
if clientToken == authHeader {
34+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key format")
35+
return
36+
}
37+
username, ok := s.userManager.Authenticate(clientToken)
38+
if !ok {
39+
writeJSONError(w, r, http.StatusUnauthorized, "authentication_error", "invalid api key")
40+
return
41+
}
4442

45-
userConfig := s.userConfigMap[username]
46-
if userConfig == nil {
47-
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "user config not found")
48-
return
43+
userConfig = s.userConfigMap[username]
44+
var err error
45+
provider, err = credentialForUser(s.userConfigMap, s.providers, username)
46+
if err != nil {
47+
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
48+
return
49+
}
50+
} else {
51+
provider = noUserCredentialProvider(s.providers, s.options)
4952
}
50-
51-
provider, err := credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, username)
52-
if err != nil {
53-
writeJSONError(w, r, http.StatusInternalServerError, "api_error", err.Error())
53+
if provider == nil {
54+
writeJSONError(w, r, http.StatusInternalServerError, "api_error", "no credential available")
5455
return
5556
}
5657

@@ -72,10 +73,10 @@ func (s *Service) computeAggregatedUtilization(provider credentialProvider, user
7273
if !credential.isAvailable() {
7374
continue
7475
}
75-
if userConfig.ExternalCredential != "" && credential.tagName() == userConfig.ExternalCredential {
76+
if userConfig != nil && userConfig.ExternalCredential != "" && credential.tagName() == userConfig.ExternalCredential {
7677
continue
7778
}
78-
if !userConfig.AllowExternalUsage && credential.isExternal() {
79+
if userConfig != nil && !userConfig.AllowExternalUsage && credential.isExternal() {
7980
continue
8081
}
8182
weight := credential.planWeight()
@@ -100,7 +101,7 @@ func (s *Service) computeAggregatedUtilization(provider credentialProvider, user
100101
}
101102

102103
func (s *Service) rewriteResponseHeadersForExternalUser(headers http.Header, userConfig *option.OCMUser) {
103-
provider, err := credentialForUser(s.userConfigMap, s.providers, s.legacyProvider, userConfig.Name)
104+
provider, err := credentialForUser(s.userConfigMap, s.providers, userConfig.Name)
104105
if err != nil {
105106
return
106107
}

0 commit comments

Comments
 (0)