Skip to content

Commit

Permalink
Fixed an issue with subpaths in resources policies (#2856)
Browse files Browse the repository at this point in the history
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
  • Loading branch information
bexsoft authored Jun 8, 2023
1 parent b460354 commit fe7be4e
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ const BrowserHandler = () => {
}

const permitItems = permissionItems(
bucketName,
response.bucketName || bucketName,
pathPrefix,
allowResources || []
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface WebsocketResponse {
request_end?: boolean;
data?: ObjectResponse[];
prefix?: string;
bucketName?: string;
}

export interface ObjectResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ export const permissionItems = (
return null;
}

const returnElements: BucketObjectItem[] = [];
let returnElements: BucketObjectItem[] = [];

// We split current path
const splitCurrentPath = currentPath.split("/");
Expand Down Expand Up @@ -354,6 +354,14 @@ export const permissionItems = (

let pathToRouteElements: string[] = [];

// We verify if currentPath is contained in the path begin, if is not contained the user has no access to this subpath
const cleanCurrPath = currentPath.replace(/\/$/, "");

if (!prefixItem.startsWith(cleanCurrPath) && currentPath !== "") {
return;
}

// For every split element we iterate and check if we can construct a URL
splitItems.every((splitElement, index) => {
if (!splitElement.includes("*") && splitElement !== "") {
if (splitElement !== splitCurrentPath[index]) {
Expand All @@ -380,5 +388,20 @@ export const permissionItems = (
}
});

// We clean duplicated name entries
if (returnElements.length > 0) {
let clElements: BucketObjectItem[] = [];
let keys: string[] = [];

returnElements.forEach((itm) => {
if (!keys.includes(itm.name)) {
clElements.push(itm);
keys.push(itm.name);
}
});

returnElements = clElements;
}

return returnElements;
};
72 changes: 72 additions & 0 deletions portal-ui/tests/permissions-7/resourceTesting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ import {
fixture("Test resources policy").page("http://localhost:9090/");

const bucket1 = "testcondition";
const bucket3 = "my-company";
const test1BucketBrowseButton = namedTestBucketBrowseButtonFor(bucket1);
const test3BucketBrowseButton = namedTestBucketBrowseButtonFor(bucket3);
export const file = Selector(".ReactVirtualized__Table__rowColumn").withText(
"test.txt"
);
export const deniedError = Selector(".message-text").withText("Access Denied.");

test
.before(async (t) => {
await functions.setUpNamedBucket(t, bucket1);
Expand Down Expand Up @@ -142,3 +146,71 @@ test
.after(async (t) => {
await functions.cleanUpNamedBucketAndUploads(t, bucket1);
});

test
.before(async (t) => {
await functions.setUpNamedBucket(t, bucket3);
await functions.uploadNamedObjectToBucket(
t,
bucket3,
"test.txt",
"portal-ui/tests/uploads/test.txt"
);
await functions.uploadNamedObjectToBucket(
t,
bucket3,
"home/UserY/test.txt",
"portal-ui/tests/uploads/test.txt"
);
await functions.uploadNamedObjectToBucket(
t,
bucket3,
"home/UserX/test.txt",
"portal-ui/tests/uploads/test.txt"
);
await functions.uploadNamedObjectToBucket(
t,
bucket3,
"home/User/test.txt",
"portal-ui/tests/uploads/test.txt"
);
await functions.uploadNamedObjectToBucket(
t,
bucket3,
"home/User/secondlevel/thirdlevel/test.txt",
"portal-ui/tests/uploads/test.txt"
);
})("User can browse from sub levels as policy has wildcard", async (t) => {
await t
.useRole(roles.conditions3)
.navigateTo(`http://localhost:9090/browser`)
.click(test3BucketBrowseButton)
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("home"))
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("User"))
.wait(1500)
.expect(file.exists)
.ok()
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("secondlevel")
)
.wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("thirdlevel")
)
.wait(1500)
.expect(file.exists)
.ok()
.navigateTo(`http://localhost:9090/browser`)
.click(test3BucketBrowseButton)
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("home"))
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("UserX"))
.expect(deniedError.exists)
.ok();
})
.after(async (t) => {
await functions.cleanUpNamedBucketAndUploads(t, bucket3);
});
36 changes: 36 additions & 0 deletions portal-ui/tests/policies/conditionsPolicy3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUserToSeeBucketListInTheConsole",
"Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::*"]
},
{
"Sid": "AllowRootAndHomeListingOfCompanyBucket",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::my-company"],
"Condition": {
"StringEquals": {
"s3:prefix": ["", "home/", "home/User"],
"s3:delimiter": ["/"]
}
}
},
{
"Sid": "AllowListingOfUserFolder",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::my-company"],
"Condition": { "StringLike": { "s3:prefix": ["home/User/*"] } }
},
{
"Sid": "AllowAllS3ActionsInUserFolder",
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": ["arn:aws:s3:::my-company/home/User/*"]
}
]
}
2 changes: 2 additions & 0 deletions portal-ui/tests/scripts/cleanup-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ remove_users() {
mc admin user remove minio prefix-policy-ui-crash-$TIMESTAMP
mc admin user remove minio conditions-$TIMESTAMP
mc admin user remove minio conditions-2-$TIMESTAMP
mc admin user remove minio conditions-3-$TIMESTAMP
}

remove_policies() {
Expand All @@ -54,6 +55,7 @@ remove_policies() {
mc admin policy remove minio fix-prefix-policy-ui-crash-$TIMESTAMP
mc admin policy remove minio conditions-policy-$TIMESTAMP
mc admin policy remove minio conditions-policy-2-$TIMESTAMP
mc admin policy remove minio conditions-policy-3-$TIMESTAMP
}

__init__() {
Expand Down
3 changes: 3 additions & 0 deletions portal-ui/tests/scripts/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ create_policies() {
mc admin policy create minio delete-object-with-prefix-$TIMESTAMP portal-ui/tests/policies/deleteObjectWithPrefix.json
mc admin policy create minio conditions-policy-$TIMESTAMP portal-ui/tests/policies/conditionsPolicy.json
mc admin policy create minio conditions-policy-2-$TIMESTAMP portal-ui/tests/policies/conditionsPolicy2.json
mc admin policy create minio conditions-policy-3-$TIMESTAMP portal-ui/tests/policies/conditionsPolicy3.json
}

create_users() {
Expand Down Expand Up @@ -77,6 +78,7 @@ create_users() {
mc admin user add minio delete-object-with-prefix-$TIMESTAMP deleteobjectwithprefix1234
mc admin user add minio conditions-$TIMESTAMP conditions1234
mc admin user add minio conditions-2-$TIMESTAMP conditions1234
mc admin user add minio conditions-3-$TIMESTAMP conditions1234
}

create_buckets() {
Expand Down Expand Up @@ -111,4 +113,5 @@ assign_policies() {
mc admin policy attach minio delete-object-with-prefix-$TIMESTAMP --user delete-object-with-prefix-$TIMESTAMP
mc admin policy attach minio conditions-policy-$TIMESTAMP --user conditions-$TIMESTAMP
mc admin policy attach minio conditions-policy-2-$TIMESTAMP --user conditions-2-$TIMESTAMP
mc admin policy attach minio conditions-policy-3-$TIMESTAMP --user conditions-3-$TIMESTAMP
}
2 changes: 2 additions & 0 deletions portal-ui/tests/scripts/permissions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ remove_users() {
mc admin user remove minio delete-object-with-prefix-"$TIMESTAMP"
mc admin user remove minio conditions-"$TIMESTAMP"
mc admin user remove minio conditions-2-"$TIMESTAMP"
mc admin user remove minio conditions-3-"$TIMESTAMP"
}

remove_policies() {
Expand All @@ -63,6 +64,7 @@ remove_policies() {
mc admin policy remove minio delete-object-with-prefix-"$TIMESTAMP"
mc admin policy remove conditions-policy-"$TIMESTAMP"
mc admin policy remove conditions-policy-2-"$TIMESTAMP"
mc admin policy remove conditions-policy-3-"$TIMESTAMP"
}

remove_buckets() {
Expand Down
11 changes: 11 additions & 0 deletions portal-ui/tests/utils/roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,14 @@ export const conditions2 = Role(
},
{ preserveUrl: true }
);

export const conditions3 = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "conditions-3-" + unixTimestamp)
.typeText("#secretKey", "conditions1234")
.click(submitButton);
},
{ preserveUrl: true }
);
1 change: 1 addition & 0 deletions restapi/admin_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type WSResponse struct {
Error string `json:"error,omitempty"`
RequestEnd bool `json:"request_end,omitempty"`
Prefix string `json:"prefix,omitempty"`
BucketName string `json:"bucketName,omitempty"`
Data []ObjectResponse `json:"data,omitempty"`
}

Expand Down
14 changes: 8 additions & 6 deletions restapi/ws_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
}
if lsObj.Err != nil {
writeChannel <- WSResponse{
RequestID: messageRequest.RequestID,
Error: lsObj.Err.Error(),
Prefix: messageRequest.Prefix,
RequestID: messageRequest.RequestID,
Error: lsObj.Err.Error(),
Prefix: messageRequest.Prefix,
BucketName: messageRequest.BucketName,
}

continue
Expand Down Expand Up @@ -177,9 +178,10 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
for lsObj := range startRewindListing(ctx, mcS3C, objectRqConfigs) {
if lsObj.Err != nil {
writeChannel <- WSResponse{
RequestID: messageRequest.RequestID,
Error: lsObj.Err.String(),
Prefix: messageRequest.Prefix,
RequestID: messageRequest.RequestID,
Error: lsObj.Err.String(),
Prefix: messageRequest.Prefix,
BucketName: messageRequest.BucketName,
}

continue
Expand Down

0 comments on commit fe7be4e

Please sign in to comment.