(rw http.ResponseWriter, r *http.Request, instanceID string, agentName string)
| 132 | } |
| 133 | |
| 134 | func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, instanceID string, agentName string) { |
| 135 | ctx := r.Context() |
| 136 | // Instance identity auth happens before the agent has a session token, so |
| 137 | // these lookups must use a restricted system context. |
| 138 | //nolint:gocritic // Instance identity auth happens before agent auth. |
| 139 | systemCtx := dbauthz.AsSystemRestricted(ctx) |
| 140 | agentName = strings.TrimSpace(agentName) |
| 141 | |
| 142 | agents, err := api.Database.GetWorkspaceBuildAgentsByInstanceID(systemCtx, instanceID) |
| 143 | if err != nil { |
| 144 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 145 | Message: "Internal error fetching workspace agent.", |
| 146 | Detail: err.Error(), |
| 147 | }) |
| 148 | return |
| 149 | } |
| 150 | if len(agents) == 0 { |
| 151 | httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ |
| 152 | Message: fmt.Sprintf("Instance with id %q not found.", instanceID), |
| 153 | }) |
| 154 | return |
| 155 | } |
| 156 | |
| 157 | selected := agents[0] |
| 158 | if agentName != "" { |
| 159 | found := false |
| 160 | for _, candidate := range agents { |
| 161 | if candidate.WorkspaceAgent.Name == agentName { |
| 162 | selected = candidate |
| 163 | found = true |
| 164 | break |
| 165 | } |
| 166 | } |
| 167 | if !found { |
| 168 | httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ |
| 169 | Message: fmt.Sprintf("No agent found with instance ID %q and name %q.", instanceID, agentName), |
| 170 | }) |
| 171 | return |
| 172 | } |
| 173 | } else if len(agents) != 1 { |
| 174 | // Include agent names in the error message to help operators |
| 175 | // configure CODER_AGENT_NAME. The caller has already proven |
| 176 | // cloud instance identity, so agent names are not sensitive |
| 177 | // here. |
| 178 | names := make([]string, len(agents)) |
| 179 | for i, candidate := range agents { |
| 180 | names[i] = candidate.WorkspaceAgent.Name |
| 181 | } |
| 182 | sort.Strings(names) |
| 183 | httpapi.Write(ctx, rw, http.StatusConflict, codersdk.Response{ |
| 184 | Message: fmt.Sprintf( |
| 185 | "Multiple agents found with instance ID %q. Set CODER_AGENT_NAME to one of: %s", |
| 186 | instanceID, |
| 187 | strings.Join(names, ", "), |
| 188 | ), |
| 189 | }) |
| 190 | return |
| 191 | } |
no test coverage detected