Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 0cb2ff8

Browse files
[chore] disallow adding authorization on dotcom (#49426)
## Description This changes previous behavior, where authorization was enforced on dotcom for github and gitlab code hosts. We do not have any private code on dotcom, show error when you try adding a private repo to dotcom and this is the final nail in the coffin, by not even allowing to specify that you want to enforce permissions on dotcom. Kudos to @pjlast for pointing me to the right place 🙇 ## Test plan unit tests changed, manual test --------- Co-authored-by: Alex Ostrikov <alex.ostrikov@sourcegraph.com>
1 parent cc8324a commit 0cb2ff8

File tree

2 files changed

+47
-73
lines changed

2 files changed

+47
-73
lines changed

internal/database/external_services.go

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -502,25 +502,16 @@ func validatePerforceConnection(perforceValidators []func(*schema.PerforceConnec
502502
return err
503503
}
504504

505-
// upsertAuthorizationToExternalService adds "authorization" field to the
506-
// external service config when not yet present for GitHub and GitLab.
507-
func upsertAuthorizationToExternalService(kind, config string) (string, error) {
508-
switch kind {
509-
case extsvc.KindGitHub:
510-
return jsonc.Edit(config, &schema.GitHubAuthorization{}, "authorization")
511-
512-
case extsvc.KindGitLab:
513-
return jsonc.Edit(config,
514-
&schema.GitLabAuthorization{
515-
IdentityProvider: schema.IdentityProvider{
516-
Oauth: &schema.OAuthIdentity{
517-
Type: "oauth",
518-
},
519-
},
520-
},
521-
"authorization")
522-
}
523-
return config, nil
505+
// disablePermsSyncingForExternalService removes "authorization" or
506+
// "enforcePermissions" fields from the external service config
507+
// when present on the external service config.
508+
func disablePermsSyncingForExternalService(config string) (string, error) {
509+
withoutEnforcePermissions, err := jsonc.Remove(config, "enforcePermissions")
510+
// in case removing "enforcePermissions" fails, we try to remove "authorization" anyway
511+
if err != nil {
512+
withoutEnforcePermissions = config
513+
}
514+
return jsonc.Remove(withoutEnforcePermissions, "authorization")
524515
}
525516

526517
func (e *externalServiceStore) Create(ctx context.Context, confGet func() *conf.Unified, es *types.ExternalService) error {
@@ -538,11 +529,11 @@ func (e *externalServiceStore) Create(ctx context.Context, confGet func() *conf.
538529
return err
539530
}
540531

541-
// 🚨 SECURITY: For all GitHub and GitLab code host connections on Sourcegraph
542-
// Cloud, we always want to enforce repository permissions using OAuth to
543-
// prevent unexpected resource leaking.
532+
// 🚨 SECURITY: For all code host connections on Sourcegraph.com,
533+
// we always want to disable repository permissions to prevent
534+
// permission syncing from trying to sync permissions from public code.
544535
if envvar.SourcegraphDotComMode() {
545-
rawConfig, err = upsertAuthorizationToExternalService(es.Kind, rawConfig)
536+
rawConfig, err = disablePermsSyncingForExternalService(rawConfig)
546537
if err != nil {
547538
return err
548539
}
@@ -623,11 +614,11 @@ func (e *externalServiceStore) Upsert(ctx context.Context, svcs ...*types.Extern
623614
return errors.Wrapf(err, "validating service of kind %q", s.Kind)
624615
}
625616

626-
// 🚨 SECURITY: For all GitHub and GitLab code host connections on Sourcegraph
627-
// Cloud, we always want to enforce repository permissions using OAuth to
628-
// prevent unexpected resource leaking.
617+
// 🚨 SECURITY: For all code host connections on Sourcegraph.com,
618+
// we always want to disable repository permissions to prevent
619+
// permission syncing from trying to sync permissions from public code.
629620
if envvar.SourcegraphDotComMode() {
630-
rawConfig, err = upsertAuthorizationToExternalService(s.Kind, rawConfig)
621+
rawConfig, err = disablePermsSyncingForExternalService(rawConfig)
631622
if err != nil {
632623
return err
633624
}
@@ -849,11 +840,11 @@ func (e *externalServiceStore) Update(ctx context.Context, ps []schema.AuthProvi
849840
return err
850841
}
851842

852-
// 🚨 SECURITY: For all GitHub and GitLab code host connections on Sourcegraph
853-
// Cloud, we always want to enforce repository permissions using OAuth to
854-
// prevent unexpected resource leaking.
843+
// 🚨 SECURITY: For all code host connections on Sourcegraph.com,
844+
// we always want to disable repository permissions to prevent
845+
// permission syncing from trying to sync permissions from public code.
855846
if envvar.SourcegraphDotComMode() {
856-
unredactedConfig, err = upsertAuthorizationToExternalService(externalService.Kind, unredactedConfig)
847+
unredactedConfig, err = disablePermsSyncingForExternalService(unredactedConfig)
857848
if err != nil {
858849
return err
859850
}

internal/database/external_services_test.go

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -557,16 +557,14 @@ func TestExternalServicesStore_Update(t *testing.T) {
557557
}
558558
}
559559

560-
func TestUpsertAuthorizationToExternalService(t *testing.T) {
560+
func TestDisablePermsSyncingForExternalService(t *testing.T) {
561561
tests := []struct {
562562
name string
563-
kind string
564563
config string
565564
want string
566565
}{
567566
{
568567
name: "github with authorization",
569-
kind: extsvc.KindGitHub,
570568
config: `
571569
{
572570
// Useful comments
@@ -580,13 +578,11 @@ func TestUpsertAuthorizationToExternalService(t *testing.T) {
580578
// Useful comments
581579
"url": "https://github.com",
582580
"repositoryQuery": ["none"],
583-
"token": "def",
584-
"authorization": {}
581+
"token": "def"
585582
}`,
586583
},
587584
{
588585
name: "github without authorization",
589-
kind: extsvc.KindGitHub,
590586
config: `
591587
{
592588
// Useful comments
@@ -599,61 +595,48 @@ func TestUpsertAuthorizationToExternalService(t *testing.T) {
599595
// Useful comments
600596
"url": "https://github.com",
601597
"repositoryQuery": ["none"],
602-
"token": "def",
603-
"authorization": {}
598+
"token": "def"
604599
}`,
605600
},
606601
{
607-
name: "gitlab with authorization",
608-
kind: extsvc.KindGitLab,
602+
name: "azure devops with enforce permissions",
609603
config: `
610604
{
611605
// Useful comments
612-
"url": "https://gitlab.com",
613-
"projectQuery": ["none"],
606+
"url": "https://dev.azure.com",
607+
"username": "horse",
614608
"token": "abc",
615-
"authorization": {}
609+
"enforcePermissions": true
616610
}`,
617611
want: `
618612
{
619613
// Useful comments
620-
"url": "https://gitlab.com",
621-
"projectQuery": ["none"],
622-
"token": "abc",
623-
"authorization": {
624-
"identityProvider": {
625-
"type": "oauth"
626-
}
627-
}
614+
"url": "https://dev.azure.com",
615+
"username": "horse",
616+
"token": "abc"
628617
}`,
629618
},
630619
{
631-
name: "gitlab without authorization",
632-
kind: extsvc.KindGitLab,
620+
name: "azure devops without enforce permissions",
633621
config: `
634622
{
635623
// Useful comments
636-
"url": "https://gitlab.com",
637-
"projectQuery": ["none"],
624+
"url": "https://dev.azure.com",
625+
"username": "horse",
638626
"token": "abc"
639627
}`,
640628
want: `
641629
{
642630
// Useful comments
643-
"url": "https://gitlab.com",
644-
"projectQuery": ["none"],
645-
"token": "abc",
646-
"authorization": {
647-
"identityProvider": {
648-
"type": "oauth"
649-
}
650-
}
631+
"url": "https://dev.azure.com",
632+
"username": "horse",
633+
"token": "abc"
651634
}`,
652635
},
653636
}
654637
for _, test := range tests {
655638
t.Run(test.name, func(t *testing.T) {
656-
got, err := upsertAuthorizationToExternalService(test.kind, test.config)
639+
got, err := disablePermsSyncingForExternalService(test.config)
657640
if err != nil {
658641
t.Fatal(err)
659642
}
@@ -666,9 +649,9 @@ func TestUpsertAuthorizationToExternalService(t *testing.T) {
666649
}
667650

668651
// This test ensures under Sourcegraph.com mode, every call of `Create`,
669-
// `Upsert` and `Update` has the "authorization" field presented in the external
652+
// `Upsert` and `Update` removes the "authorization" field in the external
670653
// service config automatically.
671-
func TestExternalServicesStore_upsertAuthorizationToExternalService(t *testing.T) {
654+
func TestExternalServicesStore_DisablePermsSyncingForExternalService(t *testing.T) {
672655
if testing.Short() {
673656
t.Skip()
674657
}
@@ -688,7 +671,7 @@ func TestExternalServicesStore_upsertAuthorizationToExternalService(t *testing.T
688671
es := &types.ExternalService{
689672
Kind: extsvc.KindGitHub,
690673
DisplayName: "GITHUB #1",
691-
Config: extsvc.NewUnencryptedConfig(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc"}`),
674+
Config: extsvc.NewUnencryptedConfig(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc", "authorization": {}}`),
692675
}
693676
err := externalServices.Create(ctx, confGet, es)
694677
require.NoError(t, err)
@@ -700,10 +683,10 @@ func TestExternalServicesStore_upsertAuthorizationToExternalService(t *testing.T
700683
t.Fatal(err)
701684
}
702685
exists := gjson.Get(cfg, "authorization").Exists()
703-
assert.True(t, exists, `"authorization" field exists`)
686+
assert.False(t, exists, `"authorization" field exists, but should not`)
704687

705688
// Reset Config field and test Upsert method
706-
es.Config.Set(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc"}`)
689+
es.Config.Set(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc", "authorization": {}}`)
707690
err = externalServices.Upsert(ctx, es)
708691
require.NoError(t, err)
709692

@@ -714,10 +697,10 @@ func TestExternalServicesStore_upsertAuthorizationToExternalService(t *testing.T
714697
t.Fatal(err)
715698
}
716699
exists = gjson.Get(cfg, "authorization").Exists()
717-
assert.True(t, exists, `"authorization" field exists`)
700+
assert.False(t, exists, `"authorization" field exists, but should not`)
718701

719702
// Reset Config field and test Update method
720-
es.Config.Set(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc"}`)
703+
es.Config.Set(`{"url": "https://github.com", "repositoryQuery": ["none"], "token": "abc", "authorization": {}}`)
721704
err = externalServices.Update(ctx,
722705
conf.Get().AuthProviders,
723706
es.ID,
@@ -734,7 +717,7 @@ func TestExternalServicesStore_upsertAuthorizationToExternalService(t *testing.T
734717
t.Fatal(err)
735718
}
736719
exists = gjson.Get(cfg, "authorization").Exists()
737-
assert.True(t, exists, `"authorization" field exists`)
720+
assert.False(t, exists, `"authorization" field exists, but should not`)
738721
}
739722

740723
func TestCountRepoCount(t *testing.T) {

0 commit comments

Comments
 (0)