/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.test.jersey.cell.auth; import static org.fest.assertions.Assertions.assertThat; import static org.junit.Assert.assertEquals; import java.util.List; import javax.ws.rs.core.HttpHeaders; import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpStatus; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import com.fujitsu.dc.common.auth.token.Role; import com.fujitsu.dc.test.categories.Integration; import com.fujitsu.dc.test.categories.Regression; import com.fujitsu.dc.test.categories.Unit; import com.fujitsu.dc.test.jersey.AbstractCase; import com.fujitsu.dc.test.jersey.DcRunner; import com.fujitsu.dc.test.setup.Setup; import com.fujitsu.dc.test.unit.core.UrlUtils; import com.fujitsu.dc.test.utils.DavResourceUtils; import com.fujitsu.dc.test.utils.Http; import com.fujitsu.dc.test.utils.ResourceUtils; import com.fujitsu.dc.test.utils.TResponse; import com.sun.jersey.test.framework.JerseyTest; /** * Basic認証のBoxレベル_Serviceコレクションリソースに対するテスト. * テストで使用するセル・ボックスは、他のBasic認証テストと同じものを使用する。 */ @RunWith(DcRunner.class) @Category({Unit.class, Integration.class, Regression.class }) public class BasicAuthSvcCollectionLevelTest extends JerseyTest { private String cellName = Setup.TEST_CELL_BASIC; private String boxName = Setup.TEST_BOX1; private String colName = "setsvccol"; private String fileName = "basicAuthResourceTestFile"; private String userName = "account4"; private String password = "password4"; private String invalidPassword = "invalidPassword"; private String token = "Basic " + Base64.encodeBase64String(String.format(("%s:%s"), userName, password).getBytes()); private String tokenForACLWrite = "Basic " + Base64.encodeBase64String(("account7:password7").getBytes()); private String invalidToken = "Basic " + Base64.encodeBase64String(String.format(("%s:%s"), userName, invalidPassword).getBytes());; /** * コンストラクタ. */ public BasicAuthSvcCollectionLevelTest() { super("com.fujitsu.dc.core.rs"); } /** * Basic認証_スキーマ情報を持たないBox配下_DavコレクションレベルAPIの操作. */ @Test public final void Basic認証_スキーマ情報を持たないBox配下_DavコレクションレベルAPIの操作() { // スキーマなしBox配下のDavコレクション svcCollectionValidate(); svcSourceCollectionValidate(); svcSourceValidate(); } /** * Basic認証ースキーマなしBox配下のサービスコレクションの操作. */ private void svcCollectionValidate() { String thisMethodColName = "basicAuthResourceSvcCollection"; // Serviceコレクションの操作 try { // Serviceコレクション // コレクション作成(Basic認証-成功) DavResourceUtils.createServiceCollection(token, HttpStatus.SC_CREATED, cellName, boxName, colName); // コレクション作成(Basic認証-失敗) TResponse res = DavResourceUtils.createServiceCollection(invalidToken, HttpStatus.SC_UNAUTHORIZED, cellName, boxName, thisMethodColName); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // コレクションPROPFIND(Basic認証-成功) DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", token, cellName, boxName + "/" + colName, 1, HttpStatus.SC_MULTI_STATUS); // コレクションPROPFIND(Basic認証-失敗) res = DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", invalidToken, cellName, boxName + "/" + colName, 1, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // コレクションPROPPATCH(Basic認証-成功) Http.request("box/proppatch.txt").with("cell", cellName).with("box", boxName) .with("path", colName) .with("token", token) .with("author1", "Author1 update") .with("hoge", "fuga") .returns().statusCode(HttpStatus.SC_MULTI_STATUS); // コレクションPROPPATCH(Basic認証-失敗) res = Http.request("box/proppatch.txt").with("cell", cellName).with("box", boxName) .with("path", colName) .with("token", invalidToken) .with("author1", "Author1 update") .with("hoge", "fuga") .returns().statusCode(HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // コレクションACL設定(Basic認証-成功) DavResourceUtils.setACLwithBox(cellName, tokenForACLWrite, HttpStatus.SC_OK, boxName, colName, "box/acl-2role-setting.txt", "role4", "role4", Role.DEFAULT_BOX_NAME, "<D:read/>", "<D:write/>", ""); // コレクションACL設定(Basic認証-失敗) res = DavResourceUtils.setACLwithBox(cellName, invalidToken, HttpStatus.SC_UNAUTHORIZED, boxName, colName, "box/acl-2role-setting.txt", "role4", "role4", Role.DEFAULT_BOX_NAME, "<D:read/>", "<D:write/>", ""); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // コレクションOPTIONS(Basic認証-成功) ResourceUtils.optionsWithAnyAuthSchema(cellName, token, colName, HttpStatus.SC_OK); // コレクションOPTIONS(Basic認証-失敗) res = ResourceUtils.optionsWithAnyAuthSchema(cellName, invalidToken, colName, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // コレクション削除(Basic認証-成功) DavResourceUtils.deleteCollectionWithAnyAuthSchema(cellName, boxName, colName, token, HttpStatus.SC_NO_CONTENT); // コレクション削除(Basic認証-失敗) res = DavResourceUtils.deleteCollectionWithAnyAuthSchema(cellName, boxName, colName, invalidToken, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); } finally { DavResourceUtils.deleteCollection(cellName, boxName, colName, AbstractCase.MASTER_TOKEN_NAME, -1); } } /** * Basic認証ースキーマなしBox配下のサービスソースコレクションの操作. */ private void svcSourceCollectionValidate() { final String srcCol = colName + "/__src/"; final String srcFile = srcCol + fileName; try { // サービスコレクション作成(Basic認証-成功) DavResourceUtils.createServiceCollection(token, HttpStatus.SC_CREATED, cellName, boxName, colName); // ファイル作成(Basic認証-成功) DavResourceUtils.createWebDavFile(cellName, token, "box/dav-put-anyAuthSchema.txt", "hoge", boxName, srcFile, HttpStatus.SC_CREATED); // サービスソースコレクションをPROPFIND(Basic認証-成功) DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", token, cellName, boxName + "/" + srcCol, 1, HttpStatus.SC_MULTI_STATUS); // サービスソースコレクションをPROPFIND(Basic認証-失敗) TResponse res = DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", invalidToken, cellName, boxName + "/" + srcCol, 1, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // サービスソースコレクションOPTIONS(Basic認証-成功) // TODO 本来は、200が返却されるべきだが、現在は環境によって動作が異なるため、401でないことのみチェックしている res = ResourceUtils.optionsWithAnyAuthSchema(cellName, token, srcCol, -1); assertThat(res.getStatusCode()).isNotEqualTo(HttpStatus.SC_UNAUTHORIZED); // サービスソースコレクションOPTIONS(Basic認証-失敗) // TODO 本来は、401が返却されるべき // res = ResourceUtils.optionsWithAnyAuthSchema(cellName, invalidToken, srcCol, // HttpStatus.SC_UNAUTHORIZED); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); } finally { DavResourceUtils.deleteWebDavFile("box/dav-delete.txt", cellName, AbstractCase.MASTER_TOKEN_NAME, srcFile, -1, boxName); DavResourceUtils.deleteCollection(cellName, boxName, colName, AbstractCase.MASTER_TOKEN_NAME, -1); } } /** * Basic認証ースキーマなしBox配下のサービスソースコレクション配下のWebDavファイルの操作. */ private void svcSourceValidate() { final String srcFile = colName + "/__src/" + fileName; try { // サービスコレクション作成(Basic認証-成功) DavResourceUtils.createServiceCollection(token, HttpStatus.SC_CREATED, cellName, boxName, colName); // ファイル作成(Basic認証-成功) DavResourceUtils.createWebDavFile(cellName, token, "box/dav-put-anyAuthSchema.txt", "hoge", boxName, srcFile, HttpStatus.SC_CREATED); // ファイル作成(Basic認証-失敗) TResponse res = DavResourceUtils.createWebDavFile(cellName, invalidToken, "box/dav-put-anyAuthSchema.txt", "hoge", boxName, srcFile, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルを取得(Basic認証-成功) DavResourceUtils.getWebDavFile(cellName, token, "box/dav-get-anyAuthSchema.txt", boxName, srcFile, HttpStatus.SC_OK); // ファイルを取得(Basic認証-失敗) res = DavResourceUtils.getWebDavFile(cellName, invalidToken, "box/dav-get-anyAuthSchema.txt", boxName, srcFile, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルをPROPFIND(Basic認証-成功) DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", token, cellName, boxName + "/" + srcFile, 1, HttpStatus.SC_MULTI_STATUS); // ファイルをPROPFIND(Basic認証-失敗) res = DavResourceUtils.propfind("box/propfind-box-allprop-anyAuthSchema.txt", invalidToken, cellName, boxName + "/" + srcFile, 1, HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルをPROPPATCH(Basic認証-成功) Http.request("box/proppatch.txt").with("cell", cellName).with("box", boxName) .with("path", srcFile) .with("token", token) .with("author1", "Author1 update") .with("hoge", "fuga") .returns().statusCode(HttpStatus.SC_MULTI_STATUS); // ファイルをPROPPATCH(Basic認証-失敗) res = Http.request("box/proppatch.txt").with("cell", cellName).with("box", boxName) .with("path", srcFile) .with("token", invalidToken) .with("author1", "Author1 update") .with("hoge", "fuga") .returns().statusCode(HttpStatus.SC_UNAUTHORIZED); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルにACL設定(Basic認証-成功) DavResourceUtils.setACLwithBox(cellName, tokenForACLWrite, HttpStatus.SC_METHOD_NOT_ALLOWED, boxName, srcFile, "box/acl-2role-setting.txt", "role4", "role4", Role.DEFAULT_BOX_NAME, "<D:read/>", "<D:write/>", ""); // ファイルにACL設定(Basic認証-失敗) res = DavResourceUtils.setACLwithBox(cellName, invalidToken, HttpStatus.SC_UNAUTHORIZED, boxName, srcFile, "box/acl-2role-setting.txt", "role4", "role4", Role.DEFAULT_BOX_NAME, "<D:read/>", "<D:write/>", ""); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルOPTIONS(Basic認証-成功) // TODO 本来は、200が返却されるべきだが、現在は環境によって動作が異なるため、401でないことのみチェックしている res = ResourceUtils.optionsWithAnyAuthSchema(cellName, token, srcFile, -1); assertThat(res.getStatusCode()).isNotEqualTo(HttpStatus.SC_UNAUTHORIZED); // ファイルOPTIONS(Basic認証-失敗) // TODO 本来は、401が返却されるべき // res = ResourceUtils.optionsWithAnyAuthSchema(cellName, invalidToken, srcFile, // HttpStatus.SC_UNAUTHORIZED); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); // ファイルを削除(Basic認証-成功) DavResourceUtils.deleteWebDavFile("box/dav-delete-anyAuthSchema.txt", cellName, token, srcFile, HttpStatus.SC_NO_CONTENT, boxName); // ファイルを削除(Basic認証-失敗) res = DavResourceUtils.deleteWebDavFile("box/dav-delete-anyAuthSchema.txt", cellName, invalidToken, srcFile, HttpStatus.SC_UNAUTHORIZED, boxName); checkAuthenticateHeaderForSchemalessBoxLevel(res, cellName); // 認証失敗のアカウントロックが解除されるのを待ち合わせる AuthTestCommon.waitForAccountLock(); } finally { DavResourceUtils.deleteWebDavFile("box/dav-delete.txt", cellName, AbstractCase.MASTER_TOKEN_NAME, srcFile, -1, boxName); DavResourceUtils.deleteCollection(cellName, boxName, colName, AbstractCase.MASTER_TOKEN_NAME, -1); } } private void checkAuthenticateHeaderForSchemalessBoxLevel(TResponse res, String expectedCellName) { // WWW-Authenticateヘッダチェック String bearer = String.format("Bearer realm=\"%s\"", UrlUtils.cellRoot(expectedCellName)); String basic = String.format("Basic realm=\"%s\"", UrlUtils.cellRoot(expectedCellName)); List<String> headers = res.getHeaders(HttpHeaders.WWW_AUTHENTICATE); assertEquals(2, headers.size()); assertThat(headers).contains(bearer); assertThat(headers).contains(basic); } }