Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Declarative way of defining a server-only DataSource?

    Hi Isomorphic,

    this might be a silly question, but is there a way of declaratively declaring a .ds.xml-DataSource to be used server-only (=with com.isomorphic.* classes only) and not from the client side?
    Can this be archived by just not listing it in the DataSourceLoader-list in the HTML (which would most likely be security by obscurity)?
    The only other way I can think of right now is to trim the requests inside of a subclassed IDACall-servlet.

    Best regards,
    Blama

    #2
    An idiom for this is mentioned in the QuickStart Guide, based on the Declarative Security system: just set requires="false".

    Comment


      #3
      Hi Isomorphic,

      thanks for the answer. I'm already using that technique in order to prevent write access to database views.
      I didn't know that I can also use it for my new use case. That this is possible means that only the client-request must be validated against the requiresRole, correct?
      If my DMI created new requests, these must not conform to the role check?
      Eg:
      • fetch-DMI on DS1 requires role1
      • fetch-DMI on DS2 requires role2
      • fetch-DMI on DS1 calls the fetch in DS2 via a com.isomorphic.datasource.DSRequest
      • User has only role1
      • User issues a fetch do DS1 from the client side

      This series of calls will work out then, correct?

      Best regards,
      Blama

      Comment


        #4
        It will if you're creating a new DSRequest() server-side, since server-created DSRequests are by default not subject to the security rules that apply to DSRequest sent from the client.

        Comment


          #5
          Hi Isomorphic,

          I'm currently writing much boilerplate ds.xml like the following:
          Code:
          <operationBinding operationType="add" requiresRole="readOnly" />
          <operationBinding operationType="update" requiresRole="readOnly" />
          <operationBinding operationType="remove" requiresRole="readOnly" />
          With this, I try to secure the DS against client-write access where this is not needed.
          Doing so, should I also include all other DSOperationTypes (besides "fetch")? This is probably a good idea, but would extend the boilerplate amount even more.

          I started searching the docs then and found docs/serverds/DataSource.requiresRole, which looks like a solution to the boilerplate-problem.
          Reading further, I found docs/serverds/OperationBinding.requiresRole which states that it is not possible to set on DataSource-level:
          Code:
          <DataSource requiresRole="serverOnly" ...
          and then in the operationBindings
          Code:
          <operationBinding operationType="fetch" requiresRole="onlyReallyRequiredRole" />
          Is there a solution to this or do I have to stick with the boilerplate?
          If so, would you forbid all DSOperationTypes (because e.g. ExcelExport or Validation might be an expensive operation) or only the write access (add, update, remove)?

          Best regards,
          Blama
          Last edited by Blama; 21 Aug 2014, 04:20.

          Comment


            #6
            If this is a common pattern for you, you can implement your own .ds.xml property which you check from DataSoure.execute(), and which rejects any DSRequest which came from the client and isn't a "fetch".

            To try to avoid others being confused by your statements about requiresRole behaviors - DataSource.requiresRole and operationBinding.requiresRole can can used together. As the docs state, they are additive: if you set operationBinding.requiresRole, any roles specified by DataSource.requiresRole are still required to access that operationBinding.

            Comment


              #7
              Hi Isomorphic,

              I'm trying to implement that now and started by adding a @Override in my IDACall-subclass:

              Code:
              @Override
              public DSResponse handleDSRequest(DSRequest dsRequest, RPCManager rpc, RequestContext context) throws Exception {
              	[B]//ERROR in this line. Which method to use instead of [I]getProperty()[/I]?[/B]
              	String allowedOperationTypeList = dsRequest.getDataSource().getProperty("allowedClientOperationTypes");
              	if (allowedOperationTypeList!=null){
              		if (!allowedOperationTypeList.contains(dsRequest.getOperationType()))
              			return new DSResponse().setDataSource(dsRequest.getDataSource()).setFailure("OperationType not allowed");
              	}
              	return super.handleDSRequest(dsRequest, rpc, context);
              }
              Which method should I use instead of getProperty()? The DataSource.getProperties(...)-methods seem to be related to something else.

              I added the attribute to my .ds.xml like the following:
              Code:
              <DataSource dbName="Oracle" tableName="T_LANGUAGE" ID="T_LANGUAGE"
              		serverType="sql" [B]allowedClientOperationTypes="fetch update"[/B]>
              	<fields>
              		...
              	</fields>
              </DataSource>
              Thank you & Best regards,
              Blama

              Comment


                #8
                Please let us know what error you are experiencing. Be sure to always include this information.

                Be sure to also include your full version.

                Comment


                  #9
                  Hi Isomorphic,

                  sorry, version is v4.1p_2014-09-14.
                  I'm not experiencing an error, I'm looking for the correct method of reading a custom attribute added to the <DataSource>-tag in my .ds.xml. Basically com.isomorphic.datasource.DataSource.getProperty(String property) (not there, yet) or an alternative.

                  I found this thread, but while it is about client+server in the beginning, the solution/fix is about client only.

                  I'm pretty sure this is easy and most likely already there, but I can't find it in the docs. Browsing the available (undocumented) methods in Eclipse did also not give me a method where I'm sure that it would do the trick.

                  Best regards,
                  Blama
                  Last edited by Blama; 16 Sep 2014, 02:41. Reason: typo

                  Comment


                    #10
                    The getProperty API is indeed already there.

                    Comment


                      #11
                      Hi Isomorphic,

                      thanks for your answer. After reading the Javadoc I'm sure I read it before.
                      My problem was that the call to dsRequest.getDataSource() in my subclassed IDACall.handleDSRequest()-override returns a DataSource and I browsed its methods, while the getProperty() you linked is in BasicDataSource.

                      For users finding this thread, my implementation is as follows:

                      public class MyIDACall extends IDACall
                      Code:
                      @Override
                      public DSResponse handleDSRequest(DSRequest dsRequest, RPCManager rpc, RequestContext context) throws Exception {
                      	String allowedClientOperationTypesProperty = ((BasicDataSource) dsRequest.getDataSource()).getProperty("allowedClientOperationTypes");
                      	if (allowedClientOperationTypesProperty != null) {
                      		List<String> allowedClientOperationTypesList = new LinkedList<String>(Arrays.asList(allowedClientOperationTypesProperty.split(" ")));
                      		if (!allowedClientOperationTypesList.contains(dsRequest.getOperationType()))
                      			return new DSResponse().setDataSource(dsRequest.getDataSource()).setFailure("OperationType not allowed");
                      	}
                      	return super.handleDSRequest(dsRequest, rpc, context);
                      }
                      Usage in .ds.xml
                      Code:
                      <DataSource tableName="..." ID="..." [B]allowedClientOperationTypes="update fetch"[/B]>
                      ...
                      This way I can now whitelist client-request OperationTypes or forbid client access at all with allowedClientOperationTypes="" on a per-Datasource level.

                      I like to suggest a similar implementation as enhancement to the server framework, as IMHO this will be needed by everyone in order to protect DataSources created for server-only use without writing boilerplate xml.

                      Best regards,
                      Blama
                      Last edited by Blama; 17 Sep 2014, 06:36. Reason: typos removed

                      Comment

                      Working...
                      X