[#377] Add check of Source IP

Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
This commit is contained in:
Marina Biryukova 2024-04-17 18:21:21 +03:00
parent 3c436d8de9
commit 034396d554
3 changed files with 36 additions and 11 deletions

View file

@ -415,6 +415,7 @@ func determineProperties(r *http.Request, decoder XMLDecoder, resolver BucketRes
res := map[string]string{ res := map[string]string{
s3.PropertyKeyOwner: owner, s3.PropertyKeyOwner: owner,
common.PropertyKeyFrostFSIDGroupID: chain.FormCondSliceContainsValue(groups), common.PropertyKeyFrostFSIDGroupID: chain.FormCondSliceContainsValue(groups),
common.PropertyKeyFrostFSSourceIP: GetReqInfo(r.Context()).RemoteHost,
} }
queries := GetReqInfo(r.Context()).URL.Query() queries := GetReqInfo(r.Context()).URL.Query()

View file

@ -60,12 +60,13 @@ func (c *centerMock) Authenticate(*http.Request) (*middleware.Box, error) {
} }
type middlewareSettingsMock struct { type middlewareSettingsMock struct {
denyByDefault bool denyByDefault bool
aclEnabled bool aclEnabled bool
sourceIPHeader string
} }
func (r *middlewareSettingsMock) SourceIPHeader() string { func (r *middlewareSettingsMock) SourceIPHeader() string {
return "" return r.sourceIPHeader
} }
func (r *middlewareSettingsMock) NamespaceHeader() string { func (r *middlewareSettingsMock) NamespaceHeader() string {

View file

@ -254,7 +254,7 @@ func TestDefaultBehaviorPolicyChecker(t *testing.T) {
// check we cannot access if rules not found when settings is enabled // check we cannot access if rules not found when settings is enabled
chiRouter.middlewareSettings.denyByDefault = true chiRouter.middlewareSettings.denyByDefault = true
createBucketErr(chiRouter, ns, bktName, apiErrors.ErrAccessDenied) createBucketErr(chiRouter, ns, bktName, nil, apiErrors.ErrAccessDenied)
} }
func TestDefaultPolicyCheckerWithUserTags(t *testing.T) { func TestDefaultPolicyCheckerWithUserTags(t *testing.T) {
@ -265,7 +265,7 @@ func TestDefaultPolicyCheckerWithUserTags(t *testing.T) {
allowOperations(router, ns, []string{"s3:CreateBucket"}, engineiam.Conditions{ allowOperations(router, ns, []string{"s3:CreateBucket"}, engineiam.Conditions{
engineiam.CondStringEquals: engineiam.Condition{fmt.Sprintf(common.PropertyKeyFormatFrostFSIDUserClaim, "tag-test"): []string{"test"}}, engineiam.CondStringEquals: engineiam.Condition{fmt.Sprintf(common.PropertyKeyFormatFrostFSIDUserClaim, "tag-test"): []string{"test"}},
}) })
createBucketErr(router, ns, bktName, apiErrors.ErrAccessDenied) createBucketErr(router, ns, bktName, nil, apiErrors.ErrAccessDenied)
tags := make(map[string]string) tags := make(map[string]string)
tags["tag-test"] = "test" tags["tag-test"] = "test"
@ -291,7 +291,7 @@ func TestACLAPE(t *testing.T) {
putObjectErr(router, ns, bktNameNew, objName, nil, apiErrors.ErrAccessDenied) putObjectErr(router, ns, bktNameNew, objName, nil, apiErrors.ErrAccessDenied)
// Deny because of deny by default // Deny because of deny by default
createBucketErr(router, ns, bktName, apiErrors.ErrAccessDenied) createBucketErr(router, ns, bktName, nil, apiErrors.ErrAccessDenied)
listBucketsErr(router, ns, apiErrors.ErrAccessDenied) listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
// Allow operations and check // Allow operations and check
@ -322,7 +322,7 @@ func TestACLAPE(t *testing.T) {
// Deny operations and check // Deny operations and check
denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"}, nil) denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"}, nil)
createBucketErr(router, ns, bktName, apiErrors.ErrAccessDenied) createBucketErr(router, ns, bktName, nil, apiErrors.ErrAccessDenied)
listBucketsErr(router, ns, apiErrors.ErrAccessDenied) listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
}) })
@ -617,6 +617,25 @@ func TestAccessBoxAttributesCheck(t *testing.T) {
listObjectsV1(router, ns, bktName, "", "", "") listObjectsV1(router, ns, bktName, "", "", "")
} }
func TestSourceIPCheck(t *testing.T) {
router := prepareRouter(t)
ns, bktName, hdr := "", "bucket", "Source-Ip"
router.middlewareSettings.denyByDefault = true
// Add policy and check
allowOperations(router, ns, []string{"s3:CreateBucket"}, engineiam.Conditions{
engineiam.CondIPAddress: engineiam.Condition{"aws:SourceIp": []string{"192.0.2.0/24"}},
})
router.middlewareSettings.sourceIPHeader = hdr
header := map[string][]string{hdr: {"192.0.3.0"}}
createBucketErr(router, ns, bktName, header, apiErrors.ErrAccessDenied)
router.middlewareSettings.sourceIPHeader = ""
createBucket(router, ns, bktName)
}
func allowOperations(router *routerMock, ns string, operations []string, conditions engineiam.Conditions) { func allowOperations(router *routerMock, ns string, operations []string, conditions engineiam.Conditions) {
addPolicy(router, ns, "allow", engineiam.AllowEffect, operations, conditions) addPolicy(router, ns, "allow", engineiam.AllowEffect, operations, conditions)
} }
@ -661,19 +680,23 @@ func createSpecificBucket(router *routerMock, bktName string, old bool) {
} }
func createBucket(router *routerMock, namespace, bktName string) { func createBucket(router *routerMock, namespace, bktName string) {
w := createBucketBase(router, namespace, bktName) w := createBucketBase(router, namespace, bktName, nil)
resp := readResponse(router.t, w) resp := readResponse(router.t, w)
require.Equal(router.t, s3middleware.CreateBucketOperation, resp.Method) require.Equal(router.t, s3middleware.CreateBucketOperation, resp.Method)
} }
func createBucketErr(router *routerMock, namespace, bktName string, errCode apiErrors.ErrorCode) { func createBucketErr(router *routerMock, namespace, bktName string, header http.Header, errCode apiErrors.ErrorCode) {
w := createBucketBase(router, namespace, bktName) w := createBucketBase(router, namespace, bktName, header)
assertAPIError(router.t, w, errCode) assertAPIError(router.t, w, errCode)
} }
func createBucketBase(router *routerMock, namespace, bktName string) *httptest.ResponseRecorder { func createBucketBase(router *routerMock, namespace, bktName string, header http.Header) *httptest.ResponseRecorder {
w, r := httptest.NewRecorder(), httptest.NewRequest(http.MethodPut, "/"+bktName, nil) w, r := httptest.NewRecorder(), httptest.NewRequest(http.MethodPut, "/"+bktName, nil)
r.Header.Set(FrostfsNamespaceHeader, namespace) r.Header.Set(FrostfsNamespaceHeader, namespace)
for key := range header {
r.Header.Set(key, header.Get(key))
}
router.ServeHTTP(w, r) router.ServeHTTP(w, r)
return w return w
} }