mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 19:21:50 +00:00
Don't require a specific username for executors auth (#25786)
There is no added security by also requiring a specific user for the already secret token. This reduces complexity in setup as there is one value less to mess up.
This commit is contained in:
parent
116359a5a9
commit
2b767a9455
@ -17,13 +17,11 @@ In order for the executors to dequeue and perform work, they must be able to rea
|
||||
|
||||
The `frontend` service must define the following environment variables:
|
||||
|
||||
- `EXECUTOR_FRONTEND_USERNAME`
|
||||
- `EXECUTOR_FRONTEND_PASSWORD`
|
||||
|
||||
The `executor` service must define the following environment variables:
|
||||
|
||||
- `EXECUTOR_FRONTEND_URL`
|
||||
- `EXECUTOR_FRONTEND_USERNAME`
|
||||
- `EXECUTOR_FRONTEND_PASSWORD`
|
||||
|
||||
When using a Sourcegraph Terraform module to provision executors, the required executor environment variables can be set via:
|
||||
|
||||
@ -18,7 +18,6 @@ type Config struct {
|
||||
env.BaseConfig
|
||||
|
||||
FrontendURL string
|
||||
FrontendUsername string
|
||||
FrontendPassword string
|
||||
QueueName string
|
||||
QueuePollInterval time.Duration
|
||||
@ -38,7 +37,6 @@ type Config struct {
|
||||
|
||||
func (c *Config) Load() {
|
||||
c.FrontendURL = c.Get("EXECUTOR_FRONTEND_URL", "", "The external URL of the sourcegraph instance.")
|
||||
c.FrontendUsername = c.Get("EXECUTOR_FRONTEND_USERNAME", "", "The username supplied to the frontend.")
|
||||
c.FrontendPassword = c.Get("EXECUTOR_FRONTEND_PASSWORD", "", "The password supplied to the frontend.")
|
||||
c.QueueName = c.Get("EXECUTOR_QUEUE_NAME", "", "The name of the queue to listen to.")
|
||||
c.QueuePollInterval = c.GetInterval("EXECUTOR_QUEUE_POLL_INTERVAL", "1s", "Interval between dequeue requests.")
|
||||
@ -131,7 +129,6 @@ func (c *Config) BaseClientOptions() apiclient.BaseClientOptions {
|
||||
func (c *Config) EndpointOptions() apiclient.EndpointOptions {
|
||||
return apiclient.EndpointOptions{
|
||||
URL: c.FrontendURL,
|
||||
Username: c.FrontendUsername,
|
||||
Password: c.FrontendPassword,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,9 +44,6 @@ type EndpointOptions struct {
|
||||
// URL is the target request URL.
|
||||
URL string
|
||||
|
||||
// Username is the basic-auth username to include with all requests.
|
||||
Username string
|
||||
|
||||
// Password is the basic-auth password to include with all requests.
|
||||
Password string
|
||||
}
|
||||
@ -224,7 +221,6 @@ func (c *Client) Heartbeat(ctx context.Context, queueName string, jobIDs []int)
|
||||
func (c *Client) makeRequest(method, path string, payload interface{}) (*http.Request, error) {
|
||||
u, err := makeURL(
|
||||
c.options.EndpointOptions.URL,
|
||||
c.options.EndpointOptions.Username,
|
||||
c.options.EndpointOptions.Password,
|
||||
c.options.PathPrefix,
|
||||
path,
|
||||
@ -236,13 +232,13 @@ func (c *Client) makeRequest(method, path string, payload interface{}) (*http.Re
|
||||
return MakeJSONRequest(method, u, payload)
|
||||
}
|
||||
|
||||
func makeURL(base, username, password string, path ...string) (*url.URL, error) {
|
||||
func makeURL(base, password string, path ...string) (*url.URL, error) {
|
||||
u, err := makeRelativeURL(base, path...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.User = url.UserPassword(username, password)
|
||||
u.User = url.UserPassword("sourcegraph", password)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
|
||||
@ -402,7 +402,6 @@ func testRoute(t *testing.T, spec routeSpec, f func(client *Client)) {
|
||||
PathPrefix: "/.executors/queue",
|
||||
EndpointOptions: EndpointOptions{
|
||||
URL: ts.URL,
|
||||
Username: "test",
|
||||
Password: "hunter2",
|
||||
},
|
||||
}
|
||||
@ -418,10 +417,7 @@ func testServer(t *testing.T, spec routeSpec) *httptest.Server {
|
||||
t.Errorf("unexpected method. want=%s have=%s", spec.expectedPath, r.URL.Path)
|
||||
}
|
||||
|
||||
username, password, _ := r.BasicAuth()
|
||||
if username != spec.expectedUsername {
|
||||
t.Errorf("unexpected username. want=%s have=%s", spec.expectedUsername, username)
|
||||
}
|
||||
_, password, _ := r.BasicAuth()
|
||||
if password != spec.expectedPassword {
|
||||
t.Errorf("unexpected password. want=%s have=%s", spec.expectedPassword, password)
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ func (h *handler) prepareWorkspace(ctx context.Context, commandRunner command.Ru
|
||||
if repositoryName != "" {
|
||||
cloneURL, err := makeURL(
|
||||
h.options.ClientOptions.EndpointOptions.URL,
|
||||
h.options.ClientOptions.EndpointOptions.Username,
|
||||
h.options.ClientOptions.EndpointOptions.Password,
|
||||
h.options.GitServicePath,
|
||||
repositoryName,
|
||||
@ -59,13 +58,13 @@ func (h *handler) prepareWorkspace(ctx context.Context, commandRunner command.Ru
|
||||
return tempDir, nil
|
||||
}
|
||||
|
||||
func makeURL(base, username, password string, path ...string) (*url.URL, error) {
|
||||
func makeURL(base, password string, path ...string) (*url.URL, error) {
|
||||
u, err := makeRelativeURL(base, path...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.User = url.UserPassword(username, password)
|
||||
u.User = url.UserPassword("sourcegraph", password)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@ func TestPrepareWorkspace(t *testing.T) {
|
||||
ClientOptions: apiclient.Options{
|
||||
EndpointOptions: apiclient.EndpointOptions{
|
||||
URL: "https://test.io",
|
||||
Username: "test",
|
||||
Password: "hunter2",
|
||||
},
|
||||
},
|
||||
@ -46,7 +45,7 @@ func TestPrepareWorkspace(t *testing.T) {
|
||||
|
||||
expectedCommands := [][]string{
|
||||
{"git", "-C", dir, "init"},
|
||||
{"git", "-C", dir, "-c", "protocol.version=2", "fetch", "https://test:hunter2@test.io/internal/git/torvalds/linux", "-t", "deadbeef"},
|
||||
{"git", "-C", dir, "-c", "protocol.version=2", "fetch", "https://sourcegraph:hunter2@test.io/internal/git/torvalds/linux", "-t", "deadbeef"},
|
||||
{"git", "-C", dir, "remote", "add", "origin", "torvalds/linux"},
|
||||
{"git", "-C", dir, "checkout", "deadbeef"},
|
||||
}
|
||||
|
||||
@ -8,11 +8,9 @@ import (
|
||||
type SharedConfig struct {
|
||||
env.BaseConfig
|
||||
|
||||
FrontendUsername string
|
||||
FrontendPassword string
|
||||
}
|
||||
|
||||
func (c *SharedConfig) Load() {
|
||||
c.FrontendUsername = c.GetOptional("EXECUTOR_FRONTEND_USERNAME", "The username supplied to the frontend.")
|
||||
c.FrontendPassword = c.GetOptional("EXECUTOR_FRONTEND_PASSWORD", "The password supplied to the frontend.")
|
||||
}
|
||||
|
||||
@ -50,7 +50,8 @@ func newExecutorQueueHandler(queueOptions map[string]handler.QueueOptions, uploa
|
||||
// in which a shared key exchange can be done so safely.
|
||||
func basicAuthMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
username, password, ok := r.BasicAuth()
|
||||
// We don't care about the username. Only the password matters here.
|
||||
_, password, ok := r.BasicAuth()
|
||||
if !ok {
|
||||
// This header is required to be present with 401 responses in order to prompt the client
|
||||
// to retry the request with basic auth credentials. If we do not send this header, the
|
||||
@ -59,17 +60,12 @@ func basicAuthMiddleware(next http.Handler) http.Handler {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if sharedConfig.FrontendUsername == "" {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
log15.Error("invalid value for EXECUTOR_FRONTEND_USERNAME: no value supplied")
|
||||
return
|
||||
}
|
||||
if sharedConfig.FrontendPassword == "" {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
log15.Error("invalid value for EXECUTOR_FRONTEND_PASSWORD: no value supplied")
|
||||
return
|
||||
}
|
||||
if username != sharedConfig.FrontendUsername || password != sharedConfig.FrontendPassword {
|
||||
if password != sharedConfig.FrontendPassword {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
sharedConfig.FrontendUsername = "test"
|
||||
sharedConfig.FrontendPassword = "hunter2"
|
||||
}
|
||||
|
||||
@ -37,18 +36,8 @@ func TestInternalProxyAuthTokenMiddleware(t *testing.T) {
|
||||
t.Errorf("unexpected www-authenticate header. want=%q have=%q", `Basic realm="Sourcegraph"`, value)
|
||||
}
|
||||
|
||||
// wrong username
|
||||
req.SetBasicAuth(strings.ToUpper(sharedConfig.FrontendUsername), sharedConfig.FrontendPassword)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error performing request: %s", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Errorf("unexpected status code. want=%d have=%d", http.StatusForbidden, resp.StatusCode)
|
||||
}
|
||||
|
||||
// wrong password
|
||||
req.SetBasicAuth(sharedConfig.FrontendUsername, strings.ToUpper(sharedConfig.FrontendPassword))
|
||||
req.SetBasicAuth("anything", strings.ToUpper(sharedConfig.FrontendPassword))
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error performing request: %s", err)
|
||||
@ -58,7 +47,7 @@ func TestInternalProxyAuthTokenMiddleware(t *testing.T) {
|
||||
}
|
||||
|
||||
// correct token
|
||||
req.SetBasicAuth(sharedConfig.FrontendUsername, sharedConfig.FrontendPassword)
|
||||
req.SetBasicAuth("anything", sharedConfig.FrontendPassword)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error performing request: %s", err)
|
||||
|
||||
@ -35,13 +35,13 @@ func createAndAttachInternalAccessToken(ctx context.Context, s batchesStore, job
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func makeURL(base, username, password string) (string, error) {
|
||||
func makeURL(base, password string) (string, error) {
|
||||
u, err := url.Parse(base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
u.User = url.UserPassword(username, password)
|
||||
u.User = url.UserPassword("sourcegraph", password)
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
@ -106,12 +106,12 @@ func transformBatchSpecWorkspaceExecutionJobRecord(ctx context.Context, s batche
|
||||
|
||||
frontendURL := conf.Get().ExternalURL
|
||||
|
||||
srcEndpoint, err := makeURL(frontendURL, config.Shared.FrontendUsername, config.Shared.FrontendPassword)
|
||||
srcEndpoint, err := makeURL(frontendURL, config.Shared.FrontendPassword)
|
||||
if err != nil {
|
||||
return apiclient.Job{}, err
|
||||
}
|
||||
|
||||
redactedSrcEndpoint, err := makeURL(frontendURL, "USERNAME_REMOVED", "PASSWORD_REMOVED")
|
||||
redactedSrcEndpoint, err := makeURL(frontendURL, "PASSWORD_REMOVED")
|
||||
if err != nil {
|
||||
return apiclient.Job{}, err
|
||||
}
|
||||
@ -151,7 +151,6 @@ func transformBatchSpecWorkspaceExecutionJobRecord(ctx context.Context, s batche
|
||||
// (in src-cli). We only pass the constructed URL to src-cli, which we trust not to
|
||||
// ship the values to a third party, but not to trust to ensure the values are absent
|
||||
// from the command's stdout or stderr streams.
|
||||
config.Shared.FrontendUsername: "USERNAME_REMOVED",
|
||||
config.Shared.FrontendPassword: "PASSWORD_REMOVED",
|
||||
|
||||
// 🚨 SECURITY: Redact the access token used for src-cli to talk to
|
||||
|
||||
@ -41,7 +41,6 @@ func TestTransformBatchSpecWorkspaceExecutionJobRecord(t *testing.T) {
|
||||
})
|
||||
config := &Config{
|
||||
Shared: &config.SharedConfig{
|
||||
FrontendUsername: "test*",
|
||||
FrontendPassword: "hunter2",
|
||||
},
|
||||
}
|
||||
@ -109,16 +108,15 @@ func TestTransformBatchSpecWorkspaceExecutionJobRecord(t *testing.T) {
|
||||
},
|
||||
Dir: ".",
|
||||
Env: []string{
|
||||
"SRC_ENDPOINT=https://test%2A:hunter2@test.io",
|
||||
"SRC_ENDPOINT=https://sourcegraph:hunter2@test.io",
|
||||
"SRC_ACCESS_TOKEN=" + accessToken,
|
||||
},
|
||||
},
|
||||
},
|
||||
RedactedValues: map[string]string{
|
||||
"https://test%2A:hunter2@test.io": "https://USERNAME_REMOVED:PASSWORD_REMOVED@test.io",
|
||||
"test*": "USERNAME_REMOVED",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
accessToken: "SRC_ACCESS_TOKEN_REMOVED",
|
||||
"https://sourcegraph:hunter2@test.io": "https://sourcegraph:PASSWORD_REMOVED@test.io",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
accessToken: "SRC_ACCESS_TOKEN_REMOVED",
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, job); diff != "" {
|
||||
|
||||
@ -36,12 +36,12 @@ func transformRecord(index store.Index, config *Config) (apiclient.Job, error) {
|
||||
|
||||
frontendURL := conf.Get().ExternalURL
|
||||
|
||||
srcEndpoint, err := makeURL(frontendURL, config.Shared.FrontendUsername, config.Shared.FrontendPassword)
|
||||
srcEndpoint, err := makeURL(frontendURL, config.Shared.FrontendPassword)
|
||||
if err != nil {
|
||||
return apiclient.Job{}, err
|
||||
}
|
||||
|
||||
redactedSrcEndpoint, err := makeURL(frontendURL, "USERNAME_REMOVED", "PASSWORD_REMOVED")
|
||||
redactedSrcEndpoint, err := makeURL(frontendURL, "PASSWORD_REMOVED")
|
||||
if err != nil {
|
||||
return apiclient.Job{}, err
|
||||
}
|
||||
@ -89,18 +89,17 @@ func transformRecord(index store.Index, config *Config) (apiclient.Job, error) {
|
||||
// (in src-cli). We only pass the constructed URL to src-cli, which we trust not to
|
||||
// ship the values to a third party, but not to trust to ensure the values are absent
|
||||
// from the command's stdout or stderr streams.
|
||||
config.Shared.FrontendUsername: "USERNAME_REMOVED",
|
||||
config.Shared.FrontendPassword: "PASSWORD_REMOVED",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeURL(base, username, password string) (string, error) {
|
||||
func makeURL(base, password string) (string, error) {
|
||||
u, err := url.Parse(base)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
u.User = url.UserPassword(username, password)
|
||||
u.User = url.UserPassword("sourcegraph", password)
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@ func TestTransformRecord(t *testing.T) {
|
||||
})
|
||||
config := &Config{
|
||||
Shared: &config.SharedConfig{
|
||||
FrontendUsername: "test*",
|
||||
FrontendPassword: "hunter2",
|
||||
},
|
||||
}
|
||||
@ -75,13 +74,12 @@ func TestTransformRecord(t *testing.T) {
|
||||
"-associated-index-id", "42",
|
||||
},
|
||||
Dir: "web",
|
||||
Env: []string{"SRC_ENDPOINT=https://test%2A:hunter2@test.io"},
|
||||
Env: []string{"SRC_ENDPOINT=https://sourcegraph:hunter2@test.io"},
|
||||
},
|
||||
},
|
||||
RedactedValues: map[string]string{
|
||||
"https://test%2A:hunter2@test.io": "https://USERNAME_REMOVED:PASSWORD_REMOVED@test.io",
|
||||
"test*": "USERNAME_REMOVED",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
"https://sourcegraph:hunter2@test.io": "https://sourcegraph:PASSWORD_REMOVED@test.io",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, job); diff != "" {
|
||||
@ -117,7 +115,6 @@ func TestTransformRecordWithoutIndexer(t *testing.T) {
|
||||
})
|
||||
config := &Config{
|
||||
Shared: &config.SharedConfig{
|
||||
FrontendUsername: "test*",
|
||||
FrontendPassword: "hunter2",
|
||||
},
|
||||
}
|
||||
@ -157,13 +154,12 @@ func TestTransformRecordWithoutIndexer(t *testing.T) {
|
||||
"-associated-index-id", "42",
|
||||
},
|
||||
Dir: "",
|
||||
Env: []string{"SRC_ENDPOINT=https://test%2A:hunter2@test.io"},
|
||||
Env: []string{"SRC_ENDPOINT=https://sourcegraph:hunter2@test.io"},
|
||||
},
|
||||
},
|
||||
RedactedValues: map[string]string{
|
||||
"https://test%2A:hunter2@test.io": "https://USERNAME_REMOVED:PASSWORD_REMOVED@test.io",
|
||||
"test*": "USERNAME_REMOVED",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
"https://sourcegraph:hunter2@test.io": "https://sourcegraph:PASSWORD_REMOVED@test.io",
|
||||
"hunter2": "PASSWORD_REMOVED",
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, job); diff != "" {
|
||||
|
||||
@ -89,7 +89,6 @@ env:
|
||||
|
||||
# Required for frontend and executor to communicate
|
||||
EXECUTOR_FRONTEND_URL: http://localhost:3080
|
||||
EXECUTOR_FRONTEND_USERNAME: executor
|
||||
EXECUTOR_FRONTEND_PASSWORD: hunter2
|
||||
|
||||
# Disable firecracker inside executor in dev
|
||||
@ -444,7 +443,7 @@ commands:
|
||||
<<: *executor_template
|
||||
cmd: |
|
||||
env TMPDIR="$HOME/.sourcegraph/batches-executor-temp" \
|
||||
sudo --preserve-env=TMPDIR,EXECUTOR_QUEUE_NAME,SRC_PROF_HTTP,EXECUTOR_FRONTEND_URL,EXECUTOR_FRONTEND_USERNAME,EXECUTOR_FRONTEND_PASSWORD,EXECUTOR_USE_FIRECRACKER,EXECUTOR_IMAGE_ARCHIVE_PATH \
|
||||
sudo --preserve-env=TMPDIR,EXECUTOR_QUEUE_NAME,SRC_PROF_HTTP,EXECUTOR_FRONTEND_URL,EXECUTOR_FRONTEND_PASSWORD,EXECUTOR_USE_FIRECRACKER,EXECUTOR_IMAGE_ARCHIVE_PATH \
|
||||
.bin/executor
|
||||
env:
|
||||
EXECUTOR_USE_FIRECRACKER: true
|
||||
|
||||
Loading…
Reference in New Issue
Block a user