Skip to content

Commit 6385d6f

Browse files
iQQBotCopilot
andauthored
[ws-proxy] prevent podIP being used with many workspaces (#20826)
* [ws-proxy] prevent podIP being used with many workspaces * Update components/ws-proxy/pkg/proxy/infoprovider.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 1f06a53 commit 6385d6f

File tree

1 file changed

+66
-12
lines changed

1 file changed

+66
-12
lines changed

components/ws-proxy/pkg/proxy/infoprovider.go

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
const (
3232
workspaceIndex = "workspaceIndex"
33+
ipAddressIndex = "ipAddressIndex"
3334
)
3435

3536
// getPortStr extracts the port part from a given URL string. Returns "" if parsing fails or port is not specified.
@@ -77,6 +78,15 @@ func NewCRDWorkspaceInfoProvider(client client.Client, scheme *runtime.Scheme) (
7778

7879
return nil, xerrors.Errorf("object is not a WorkspaceInfo")
7980
},
81+
ipAddressIndex: func(obj interface{}) ([]string, error) {
82+
if workspaceInfo, ok := obj.(*common.WorkspaceInfo); ok {
83+
if workspaceInfo.IPAddress == "" {
84+
return nil, nil
85+
}
86+
return []string{workspaceInfo.IPAddress}, nil
87+
}
88+
return nil, xerrors.Errorf("object is not a WorkspaceInfo")
89+
},
8090
}
8191
contextIndexers := cache.Indexers{
8292
workspaceIndex: func(obj interface{}) ([]string, error) {
@@ -96,29 +106,73 @@ func NewCRDWorkspaceInfoProvider(client client.Client, scheme *runtime.Scheme) (
96106
}, nil
97107
}
98108

99-
// WorkspaceInfo return the WorkspaceInfo available for the given workspaceID.
109+
// WorkspaceInfo returns the WorkspaceInfo for the given workspaceID.
110+
// It performs validation to ensure the workspace is unique and properly associated with its IP address.
100111
func (r *CRDWorkspaceInfoProvider) WorkspaceInfo(workspaceID string) *common.WorkspaceInfo {
101112
workspaces, err := r.store.ByIndex(workspaceIndex, workspaceID)
102113
if err != nil {
103114
return nil
104115
}
105116

106-
if len(workspaces) >= 1 {
107-
if len(workspaces) != 1 {
108-
log.Warnf("multiple instances (%d) for workspace %s", len(workspaces), workspaceID)
109-
}
117+
if len(workspaces) == 0 {
118+
return nil
119+
}
110120

111-
sort.Slice(workspaces, func(i, j int) bool {
112-
a := workspaces[i].(*common.WorkspaceInfo)
113-
b := workspaces[j].(*common.WorkspaceInfo)
121+
if len(workspaces) > 1 {
122+
log.WithField("workspaceID", workspaceID).WithField("instanceCount", len(workspaces)).Warn("multiple workspace instances found")
123+
}
114124

115-
return a.StartedAt.After(b.StartedAt)
116-
})
125+
sort.Slice(workspaces, func(i, j int) bool {
126+
a := workspaces[i].(*common.WorkspaceInfo)
127+
b := workspaces[j].(*common.WorkspaceInfo)
128+
return a.StartedAt.After(b.StartedAt)
129+
})
130+
131+
wsInfo := workspaces[0].(*common.WorkspaceInfo)
132+
133+
if wsInfo.IPAddress == "" {
134+
return wsInfo
135+
}
136+
137+
if conflict, err := r.validateIPAddressConflict(workspaceID, wsInfo.IPAddress); conflict || err != nil {
138+
return nil
139+
}
117140

118-
return workspaces[0].(*common.WorkspaceInfo)
141+
return wsInfo
142+
}
143+
144+
func (r *CRDWorkspaceInfoProvider) validateIPAddressConflict(workspaceID, ipAddress string) (bool, error) {
145+
wsInfos, err := r.workspacesInfoByIPAddress(ipAddress)
146+
if err != nil {
147+
log.WithError(err).WithField("workspaceID", workspaceID).WithField("ipAddress", ipAddress).Error("failed to get workspaces by IP address")
148+
return true, err
149+
}
150+
151+
if len(wsInfos) > 1 {
152+
log.WithField("workspaceID", workspaceID).WithField("ipAddress", ipAddress).WithField("workspaceCount", len(wsInfos)).Warn("multiple workspaces found for IP address")
153+
return true, nil
154+
}
155+
156+
if len(wsInfos) == 1 && wsInfos[0].WorkspaceID != workspaceID {
157+
log.WithField("workspaceID", workspaceID).WithField("ipAddress", ipAddress).WithField("foundWorkspaceID", wsInfos[0].WorkspaceID).Warn("workspace IP address conflict detected")
158+
return true, nil
159+
}
160+
161+
return false, nil
162+
}
163+
164+
func (r *CRDWorkspaceInfoProvider) workspacesInfoByIPAddress(ipAddress string) ([]*common.WorkspaceInfo, error) {
165+
workspaces := make([]*common.WorkspaceInfo, 0)
166+
167+
objs, err := r.store.ByIndex(ipAddressIndex, ipAddress)
168+
if err != nil {
169+
return nil, err
170+
}
171+
for _, w := range objs {
172+
workspaces = append(workspaces, w.(*common.WorkspaceInfo))
119173
}
120174

121-
return nil
175+
return workspaces, nil
122176
}
123177

124178
func (r *CRDWorkspaceInfoProvider) AcquireContext(ctx context.Context, workspaceID string, port string) (context.Context, string, error) {

0 commit comments

Comments
 (0)