package org.yamcs; import static org.junit.Assert.*; import java.util.concurrent.ExecutionException; import org.junit.Test; import org.yamcs.api.MediaType; import org.yamcs.api.YamcsApiException; import org.yamcs.api.YamcsConnectionProperties; import org.yamcs.api.rest.RestClient; import org.yamcs.api.ws.WebSocketRequest; import org.yamcs.protobuf.*; import org.yamcs.protobuf.Pvalue.ParameterData; import org.yamcs.protobuf.Pvalue.ParameterValue; import org.yamcs.protobuf.Rest.BulkGetParameterValueRequest; import org.yamcs.protobuf.Rest.BulkSetParameterValueRequest; import org.yamcs.protobuf.Rest.BulkSetParameterValueRequest.SetParameterValueRequest; import org.yamcs.protobuf.Rest.IssueCommandRequest; import org.yamcs.protobuf.Web.RestExceptionMessage; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.NamedObjectList; import org.yamcs.security.UsernamePasswordToken; import org.yamcs.utils.TimeEncoding; import io.netty.handler.codec.http.HttpMethod; public class PermissionsTest extends AbstractIntegrationTest { @Test public void testAuthenticationWebServices() throws Exception { RestClient restClient1 = getRestClient("baduser", "wrongpassword"); try { restClient1.doRequest("/user", HttpMethod.GET, "").get(); fail("should have thrown an exception"); } catch (ExecutionException e) { assertTrue(e.getCause().getMessage().contains("Unauthorized")); } restClient1.close(); } @Test public void testPermissionArchive() throws Exception { // testuser is allowed to replay integer parameters but no string parameters RestClient restClient1 = getRestClient("testuser", "password"); // Check that integer parameter replay is ok generateData("2015-03-02T10:00:00", 3600); String resource = "/archive/IntegrationTest/parameters"; resource += "/REFMDB/SUBSYS1/IntegerPara1_1_6"; resource += "?start=2015-03-02T10:10:00&stop=2015-03-02T10:10:02&order=asc"; String response = restClient1.doRequest(resource, HttpMethod.GET, "").get(); ParameterData pdata = (fromJson(response, SchemaPvalue.ParameterData.MERGE)).build(); assertNotNull(pdata); assertEquals(2, pdata.getParameterCount()); ParameterValue pv0 = pdata.getParameter(0); assertEquals("2015-03-02T10:10:00.000", pv0.getGenerationTimeUTC()); // Check that string parameter replay is denied boolean gotException = false; try { String stringId = "/REFMDB/SUBSYS1/FixedStringPara1_3_1"; resource = "/archive/IntegrationTest"; resource += stringId; resource += "?start=2015-03-02T10:10:00&stop=2015-03-02T10:10:02&order=asc"; response = restClient1.doRequest(resource, HttpMethod.GET, "").get(); pdata = (fromJson(response, SchemaPvalue.ParameterData.MERGE)).build(); if(pdata.getParameterCount() == 0) { throw new Exception("should get parameters"); } } catch(Exception e) { gotException = true; } assertTrue("Permission should be denied for String parameter", gotException); restClient1.close(); } @Test public void testPermissionSendCommand() throws Exception { RestClient restClient1 = getRestClient("testuser", "password"); // Command INT_ARG_TC is allowed WebSocketRequest wsr = new WebSocketRequest("cmdhistory", "subscribe"); wsClient.sendRequest(wsr); IssueCommandRequest cmdreq = getCommand(5, "uint32_arg", "1000"); String resp = restClient1.doRequest("/processors/IntegrationTest/realtime/commands/REFMDB/SUBSYS1/INT_ARG_TC", HttpMethod.POST, toJson(cmdreq, SchemaRest.IssueCommandRequest.WRITE)).get(); assertTrue(resp.contains("binary")); // Command FLOAT_ARG_TC is denied cmdreq = getCommand(5, "float_arg", "-15", "double_arg", "0"); try { resp = restClient1.doRequest("/processors/IntegrationTest/realtime/commands/REFMDB/SUBSYS1/FLOAT_ARG_TC", HttpMethod.POST, toJson(cmdreq, SchemaRest.IssueCommandRequest.WRITE)).get(); fail("should have thrown an exception"); } catch (ExecutionException e) { assertTrue(e.getCause().getMessage().contains("No such command")); } } @Test public void testPermissionGetParameter() throws Exception { RestClient restClient1 = getRestClient("testuser", "password"); // Allowed to subscribe to Integer parameter from cache NamedObjectList validSubscrList = getSubscription("/REFMDB/SUBSYS1/IntegerPara1_1_6", "/REFMDB/SUBSYS1/IntegerPara1_1_7"); BulkGetParameterValueRequest req = BulkGetParameterValueRequest.newBuilder().setFromCache(true).addAllId(validSubscrList.getListList()).build(); restClient1.doRequest("/processors/IntegrationTest/realtime/parameters/mget", HttpMethod.GET, toJson(req, SchemaRest.BulkGetParameterValueRequest.WRITE)).get(); // Denied to subscribe to Float parameter from cache validSubscrList = getSubscription("/REFMDB/SUBSYS1/FloatPara1_1_3", "/REFMDB/SUBSYS1/FloatPara1_1_2"); req = BulkGetParameterValueRequest.newBuilder().setFromCache(true).addAllId(validSubscrList.getListList()).build(); try { restClient1.doRequest("/processors/IntegrationTest/realtime/parameters/mget", HttpMethod.GET, toJson(req, SchemaRest.BulkGetParameterValueRequest.WRITE)).get(); fail("should have thrown an exception"); } catch (ExecutionException e) { RestExceptionMessage rem = ((YamcsApiException)e.getCause()).getRestExceptionMessage(); assertEquals("ForbiddenException", rem.getType()); } restClient1.close(); } @Test public void testPermissionSetParameter() throws Exception { RestClient restClient1 = getRestClient("operator", "password"); BulkSetParameterValueRequest.Builder bulkPvals = BulkSetParameterValueRequest.newBuilder(); bulkPvals.addRequest(SetParameterValueRequest.newBuilder() .setId(NamedObjectId.newBuilder().setName("/REFMDB/SUBSYS1/LocalPara1")) .setValue(ValueHelper.newValue(5))); try { restClient1.doRequest("/processors/IntegrationTest/realtime/parameters/mset", HttpMethod.POST, toJson(bulkPvals.build(), SchemaRest.BulkSetParameterValueRequest.WRITE)).get(); fail("should have thrown an exception"); } catch (ExecutionException e) { YamcsApiException e1 = (YamcsApiException)e.getCause(); RestExceptionMessage rem = e1.getRestExceptionMessage(); assertEquals("ForbiddenException", rem.getType()); } restClient1.close(); } @Test public void testPermissionUpdateCommandHistory() throws Exception { // testUser does not have the permission to update the command history // operator has the permission try { updateCommandHistory(getRestClient("testuser", "password")); } catch (ExecutionException e) { RestExceptionMessage rem = ((YamcsApiException)e.getCause()).getRestExceptionMessage(); assertEquals("ForbiddenException", rem.getType()); } try { updateCommandHistory(getRestClient("operator", "password")); } catch (ExecutionException e) { RestExceptionMessage rem = ((YamcsApiException)e.getCause()).getRestExceptionMessage(); assertEquals("ForbiddenException", rem.getType()); } } private String updateCommandHistory(RestClient restClient1) throws Exception { // insert a value in the command history on dummy command id Commanding.CommandId commandId = Commanding.CommandId.newBuilder().setSequenceNumber(0).setOrigin("").setGenerationTime(0).build(); Rest.UpdateCommandHistoryRequest.Builder updateHistoryRequest = Rest.UpdateCommandHistoryRequest.newBuilder().setCmdId(commandId); updateHistoryRequest.addHistoryEntry(Rest.UpdateCommandHistoryRequest.KeyValue.newBuilder().setKey("testKey1").setValue("testValue1")); return restClient1.doRequest("/processors/IntegrationTest/realtime/commandhistory/REFMDB/SUBSYS1/ONE_INT_ARG_TC", HttpMethod.POST, toJson(updateHistoryRequest.build(), SchemaRest.UpdateCommandHistoryRequest.WRITE)).get(); } private void generateData(String utcStart, int numPackets) { long t0 = TimeEncoding.parse(utcStart); for (int i=0;i <numPackets; i++) { packetGenerator.setGenerationTime(t0+1000*i); packetGenerator.generate_PKT1_1(); packetGenerator.generate_PKT1_3(); } } private RestClient getRestClient(String username, String password) { YamcsConnectionProperties ycp1 = ycp.clone(); ycp1.setAuthenticationToken(new UsernamePasswordToken(username, password)); RestClient restClient1 = new RestClient(ycp1); restClient1.setAcceptMediaType(MediaType.JSON); restClient1.setSendMediaType(MediaType.JSON); restClient1.setAutoclose(false); return restClient1; } }