package s3api import ( "net/http" "net/http/httptest" "testing" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/stretchr/testify/assert" ) // A config file the proto parser reads as empty - an unpopulated secret mount, // a singular "identity" - used to leave the gateway serving every anonymous // request, including ListBuckets and bucket creation. func TestConfigWithoutIdentitiesDeniesAnonymous(t *testing.T) { for name, config := range map[string]string{ "no identities key": `{}`, "empty": `{"identities":[]}`, "unrecognised key": `{"identity":[{"name":"admin","credentials":[{"accessKey":"adminkey","secretKey":"adminsecret"}],"actions":["Admin"]}]}`, } { t.Run(name, func(t *testing.T) { resetMemoryStore() clearEnvironmentVariableCredentials(t) path := writeTempIamConfig(t, config) iam := NewIdentityAccessManagementWithStore(&S3ApiServerOption{Config: path}, nil, "memory") assert.True(t, iam.isEnabled(), "naming a config file asks for authentication, even if it yields no identity") handlerCalled := false handler := iam.Auth(func(w http.ResponseWriter, r *http.Request) { handlerCalled = true }, s3_constants.ACTION_LIST) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/", nil)) assert.False(t, handlerCalled, "ListBuckets must not run for an anonymous caller") assert.Equal(t, http.StatusForbidden, recorder.Code) }) } } // `weed mini` and `docker run seaweedfs` name no config file and stay open. func TestNoConfigKeepsAnonymousAllowed(t *testing.T) { resetMemoryStore() clearEnvironmentVariableCredentials(t) iam := NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, nil, "memory") assert.False(t, iam.isEnabled(), "auth must stay off when no config file and no identities are configured") } // AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY register an admin identity of // their own, which would decide isAuthEnabled before the config file does. func clearEnvironmentVariableCredentials(t *testing.T) { t.Setenv("AWS_ACCESS_KEY_ID", "") t.Setenv("AWS_SECRET_ACCESS_KEY", "") } // The proto parser drops what it does not recognise, so a typo has to be named // at startup or the resulting lockout has no visible cause. func TestUnknownS3ConfigKeys(t *testing.T) { assert.Equal(t, []string{"identity"}, unknownS3ConfigKeys([]byte(`{"identity":[],"accounts":[]}`))) assert.Empty(t, unknownS3ConfigKeys([]byte(`{"identities":[],"service_accounts":[],"serviceAccounts":[],"policies":[],"groups":[]}`))) assert.Empty(t, unknownS3ConfigKeys([]byte(`{"kms":{},"sts":{},"policy":{},"providers":[],"roles":[]}`)), "sections owned by other subsystems are not typos") assert.Empty(t, unknownS3ConfigKeys([]byte(`not json`))) }