Hyperledger Composer v0.19 Hiding Historian in ACL - hyperledger

I would like to ask how to hide the Historian // Transaction log in v0.19?
I have tried this from an example -->
rule hideHistorianAccess{
description: "Deny access to Historian"
participant: "org.blockknowhow.com.Users"
operation: READ
resource: "org.hyperledger.composer.system.HistorianRecord"
action: DENY
}
rule historianAccess{
description: "Only allow members to read historian records referencing transactions they submitted."
participant(p): "org.blockknowhow.com.Users"
operation: READ
resource(r): "org.hyperledger.composer.system.HistorianRecord"
condition: (r.participantInvoking.getIdentifier() == p.getIdentifier())
action: ALLOW
}
But none of this seems to work, I would like to hide adding new participants mostly, but if that is not possible I would like to hide the complete transaction log. I have personal details in the participant fields which I would not like to make publicly accessible.

As mentioned by david_k - the context of your rules (above) in relation to ALL rules in permissions.acl would be needed to understand why you saw what you did.
It appears from a Rocketchat conversation that the issue was related to the ORDER of the rules in the ruleset, ie a more 'general' rule is evaluated ahead of the 'specific' rule in the lexical rules evaluation, and found a match (so subsequent 'specific' rule wasn't evaluated, hence why you saw those results initially).
An example of that is shown below:
'CORRECT ORDER'
// specifically allow users to see historian records they invoked
rule historianAccess{
description: "Only allow members to read historian records referencing transactions they submitted."
participant(p): "org.blockknowhow.com.Users"
operation: READ
resource(r): "org.hyperledger.composer.system.HistorianRecord"
condition: (r.participantInvoking.getIdentifier() == p.getIdentifier())
action: ALLOW
}
// prevent users from seeing historian records
rule hidehistorianAccess{
description: "Deny access to Historian"
participant: "org.blockknowhow.com.Users"
operation: READ
resource: "org.hyperledger.composer.system.HistorianRecord"
action: DENY
}
vs 'INCORRECT ORDER':
rule hidehistorianAccess{
description: "Deny access to Historian"
participant: "org.blockknowhow.com.Users"
operation: READ
resource: "org.hyperledger.composer.system.HistorianRecord"
action: DENY
}
rule historianAccess{
description: "Only allow members to read historian records referencing transactions they submitted."
participant(p): "org.blockknowhow.com.Users"
operation: READ
resource(r): "org.hyperledger.composer.system.HistorianRecord"
condition: (r.participantInvoking.getIdentifier() == p.getIdentifier())
action: ALLOW
}

I think the first rule is not needed. With your ALLOW rule for only particular participants under a strict condition, every other participant not matching the condition will get its actions denied.
I see that you found the ALLOW rule in the docs and this also looks good, I wouldn't approach it differently. But to get it running, try deleting the first rule. If that's not working out, I would recommend creating an issue at composer on Github.

Related

How to set the scope using Google Operators in Airflow

I have a task using the GCSToGoogleSheetsOperator in Airflow where Im trying to add data to a sheet.
I have added the service credential email to the sheet I want to edit with editor privileges, and received this error:
googleapiclient.errors.HttpError:
<HttpError 403 when requesting
https://sheets.googleapis.com/v4/spreadsheets/<SHEET_ID>/values/Sheet1?valueInputOption=RAW&includeValuesInResponse=false&responseValueRenderOption=FORMATTED_VALUE&responseDateTimeRenderOption=SERIAL_NUMBER&alt=json
returned "Request had insufficient authentication scopes.".
Details: "[{
'#type': 'type.googleapis.com/google.rpc.ErrorInfo',
'reason': 'ACCESS_TOKEN_SCOPE_INSUFFICIENT',
'domain': 'googleapis.com',
'metadata': {
'service': 'sheets.googleapis.com',
'method': 'google.apps.sheets.v4.SpreadsheetsService.UpdateValues'}
}]>
I cant update the sheet, but the GCS and BigQuery operators work fine.
My connection configuration looks like the following:
AIRFLOW_CONN_GOOGLE_CLOUD=google-cloud-platform://?extra__google_cloud_platform__key_path=%2Fopt%2Fairflow%2Fcredentials%2Fgoogle_credential.json
I tried following the instructions to add the scope https://www.googleapis.com/auth/spreadsheets.
Which URL encoded looks like:
AIRFLOW_CONN_GOOGLE_CLOUD=google-cloud-platform://?extra__google_cloud_platform__key_path=%2Fopt%2Fairflow%2Fcredentials%2Fgoogle_credential.json&extra__google_cloud_platform__scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets
Now, operators which previously worked error out like this:
google.api_core.exceptions.Forbidden: 403 POST https://bigquery.googleapis.com/bigquery/v2/projects/my-project/jobs?prettyPrint=false: Request had insufficient authentication scopes.
And the GCSToGoogleSheetsOperator operator still error out like this:
google.api_core.exceptions.Forbidden: 403 GET https://storage.googleapis.com/download/storage/v1/b/my-bucket/o/folder%2Fobject.csv?alt=media: Insufficient Permission: ('Request failed with status code', 403, 'Expected one of', <HTTPStatus.OK: 200>, <HTTPStatus.PARTIAL_CONTENT: 206>)
How can I set the permissions correctly to use both BigQuery, GCS and Sheets operators?
Adding a scope seems to ignore the IAM roles, so its either one or the other.
The service account had roles needed to access GCS and BigQuery, but by adding the scope https://www.googleapis.com/auth/spreadsheets, the service would ignore the privileges granted by the roles and look only at the ones specified by the scopes.
So, to recover it, you must add both the spreadsheet and cloud-platform scopes (or more strict scopes). cloud-platform will provide access to GCS and BigQuery and spreadsheets to Google Sheets API.
If you set your connection using environment variables, you have to URL encode the arguments, so to create a GOOGLE_CLOUD connection, you will have to do something like this, which is not encoded...
AIRFLOW_CONN_GOOGLE_CLOUD=google-cloud-platform://?extra__google_cloud_platform__key_path=/abs/path_to_file/credential.json&extra__google_cloud_platform__scope=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/spreadsheets
To encode, which is the version you have to use, replace /, , and ::
AIRFLOW_CONN_GOOGLE_CLOUD=google-cloud-platform://?extra__google_cloud_platform__key_path=%2Fabs%2Fpath_to_file%2Fcredentials%2Fgoshare-driver-c08e0904285b.json&extra__google_cloud_platform__scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets

Which groups allow selecting the properties allowExternalSenders or autoSubscribeNewMembers?

When I select the properties allowExternalSenders or autoSubscribeNewMembers for a group synced from an on-premise Active Directory, I get the following error via Graph API SDK:
403 Forbidden
Graph service exception Error code: AppOnlyAccessNotEnabledForTarget
Error message: App Only access is not allowed for target resource: 'a1d0c98e-fb7e-40c4-a7b5-ccf6d96cba57#34f0717f-f1a0-4894-b310-d379993504b9'.
The Graph Explorer displays the following 404 error, even though it is not a mailbox:
{
"error": {
"code": "MailboxNotEnabledForRESTAPI",
"message": "REST API is not yet supported for this mailbox.",
"innerError": {
"request-id": "5beae8eb-4a59-404f-bd42-0c6aa2a25abd",
"date": "2020-03-31T13:02:11"
}
}
}
An example request looks like this:
https://graph.microsoft.com/v1.0/groups/{id}?$select=id,deletedDateTime,assignedLicenses,description,displayName,groupTypes,licenseProcessingState,mail,mailEnabled,mailNickname,onPremisesLastSyncDateTime,onPremisesSecurityIdentifier,onPremisesSyncEnabled,onPremisesDomainName,onPremisesSamAccountName,preferredDataLocation,securityEnabled,securityIdentifier,visibility,resourceProvisioningOptions,allowExternalSenders,autoSubscribeNewMembers
Which property should I use to decide if I should try to select these properties or not? I want to avoid missing the properties for groups which actually do expose these properties, so I do not simply want to guess.
Slightly different take on this answer, Microsoft even thought only providing one API for groups, there are effectively two different objects returned, SecurityEnabled = True or False. If Security = True then you can not ask for the follow attributes
(allowExternalSenders,autoSubscribeNewMembers,hideFromAddressLists,hideFromOutlookClients)
Is this ok, NO its not ok, Microsoft needs to return null instead of providing THE WRONG ERROR MESSAGE and sending people like us into multi hour head scratchers.
In my code, I now check if securityEnabled is true or false and have a different set of attributes depending.
The mailbox is on a dedicated (on premise) Microsoft Exchange Server or is not a valid (configured) Office 365 mailbox. Contact your Exchange or Office admin to apply any of these recommended solutions.
To filter Office 365 groups you can do this:
https://graph.microsoft.com/v1.0/groups?$filter=groupTypes/any(c:c eq 'Unified')

Access Control problem in hyperledger composer for non-admin participants

I got a question regarding access control in hyperledger composer.
I have read and utilized the instructions in Hyperledger Composer v0.19 Hiding Historian in ACL, but still, I have no success.
I want to have the following scenarios:
We have different types of assets in a namespace called 'org.example.assets'. The code is like the following
namespace org.example.assets
import org.example.*
abstract asset exampleAsset identified by Id
{
o String Id
--> exampleParticipant owner
}
asset myAsset extends exampleAsset
{
o String title
o String description
o String criteriaUrl
o String logoUrl
--> exampleParticipant issuer
}
I want owners of the assets have the ability to access them, and no other participants. Example participant is simply inheriting Participant and is placed in org.example namespace.
I do not want every participant to watch the whole historian; he/she can only see the records of transactions made by him/herself
here is the permissions.acl file I have so far
rule Participant_CanAccessOwnAssets {
description: "owner has full access"
participant(p): "org.example.exampleParticipant"
operation: ALL
resource(r): "org.example.assets.exampleAsset"
condition: (p.getIdentifier() == r.owner.getIdentifier())
action: ALLOW
}
rule Participant_CanOnlyReadOwnHistorian {
description: "each party should be able to read its own record"
participant(p): "org.example.exampleParticipant"
operation: READ
resource(r): "org.hyperledger.composer.system.HistorianRecord"
condition: (p.getIdentifier() == r.participantInvoking.getIdentifier())
action: ALLOW
}
rule Participants_DenyAccessToHistorian {
description: "participants cannot access general historian"
participant: "org.example.exampleParticipant"
operation: READ
resource: "org.hyperledger.composer.system.HistorianRecord"
action: DENY
}
rule Participant_CanReadNetwork {
description: "participants can read (connect to) the business network"
participant: "org.example.exampleParticipant"
operation: READ
resource: "org.hyperledger.composer.system.Network"
action: ALLOW
}
rule NetworkAdminUser {
description: "Grant business network administrators full access to user resources"
participant: "org.hyperledger.composer.system.NetworkAdmin"
operation: ALL
resource: "**"
action: ALLOW
}
rule NetworkAdminSystem {
description: "Grant business network administrators full access to system resources"
participant: "org.hyperledger.composer.system.NetworkAdmin"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}
I connect to composer playground using my admin card, then I create a new participant and issue and identity for that paricipant. but when I try connecting to the network using my newly created card, I get the following error
Error: transaction returned with failure: AccessException: Participant 'org.pledger.PledgerParticipant#neo' does not have 'READ' access to resource 'org.hyperledger.composer.system.AssetRegistry#org.hyperledger.composer.system.HistorianRecord'
what should I do to solve this problem?
I guess there is a problem with this rule regarding the inheritance I am using, generalizing that any assets inheriting from abstract exampleAsset has an owner, but is this causing my problem?
rule Participant_CanAccessOwnAssets {
description: "owner has full access"
participant(p): "org.example.exampleParticipant"
operation: ALL
resource(r): "org.example.assets.exampleAsset"
condition: (p.getIdentifier() == r.owner.getIdentifier())
action: ALLOW
}
Before we get to the topic, just two comments regarding the ACL file:
On line 13, there is a typo ("paricipant")
On line 5, it should be "org.example.exampleAsset"
As for the question whether inheritance is an issue here, I'm not sure. But for example in the sample network "letters of credit", we also see a relationship added to an abstract class. What that means for your access control rule file is another story.
Have you tried adding the relationship on the sub classes to see if that works?

$batch request resulting in error "Default changeset implementation allows only one operation"

I am making a worklist application using SAPUI5. The problem is that when I create an entry and then create another one right after that, I get the following error:
Default changeset implementation allows only one operation.
I checked the $batch header and I see that there is a MERGE and a POST, with the MERGE updating the previous entry for some reason. Can anyone shed some light? Could it be a backend error and not a UI5 error?
Creating the new entry:
_onMetadataLoaded: function() {
var oModel = this.getView().getModel();
var that = this;
// ...
oModel.read("/USERS_SET", {
success: function(oData) {
var oProperties = {
Qmnum: "0",
Otherstuff: "cool"
};
that._oContext = that._oView.getModel().createEntry("/ENTITYSET", {
properties: oProperties
});
that.getView().setBindingContext(that._oContext);
// ...
}
});
},
handleSavePress: function(oEvent) {
// ...
this.getView().getModel().submitChanges({
success: function(oData) {
// ...
},
error: function(oError) {
// ...
}
});
},
tl-dr: Apparently you must be using the SAP Gateway. If you do not need to process those requests in one transaction then send them in different changesets. If you do not need batch calls at all consider turning it off by supplying your model with "useBatch": false upon instantiation. However if you need to process the requests together in one transaction then you have to read the details below.
In order to understand the problem you have to understand how the gateway and the batch and changeset requests work.
Batch requests consist of multiple requests bundled together. The purpose is to open only one connection and group together relevant requests so that the overhead is minimalized. Changesets form smaller blocks inside batch requests, where modification requests can be bundled and processed together in order to ensure an all-or-nothing characteristic.
So on the gateway side: there are two relevant classes for your OData service, assuming that you have used the SAP Gateway Service Builder (SEGW transaction). There is one with the ending ...DPC and one with ...DPC_EXT. Don't touch the former, it will be always regenerated when you update your service in the service builder. The latter is the one that we will need in this example. You will have to redefine at least two methods:
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_PROCESS
By default the changeset_begin method will only allow changeset processing for changesets where the number of requests equals to one. This can be handled automatically that's why a limitation exists. If there were more requests one could not ensure their processing automatically as they could have a business dependency on each other.
So make sure to allow a bundled (deferred mode) processing of changesets under the desired conditions:
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN: first call the super->/iwbep/if_mgw_appl_srv_runtime~changeset_begin method in a try catch block, then loop at it_operation_info to decide and narrow down processing only in selected cases and then allow cv_defer_mode only for the selected cases, otherwise throw a /iwbep/cx_mgw_tech_exception=>changeset_not_supported exception.
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_PROCESS: all requests will be available in the it_changeset_request. Make sure to fill the ct_changeset_response table with the responses.
METHOD /iwbep/if_mgw_appl_srv_runtime~changeset_process.
DATA:
lv_operation_counter TYPE i VALUE 0,
lr_context TYPE REF TO /iwbep/cl_mgw_request,
lr_entry_provider TYPE REF TO /iwbep/if_mgw_entry_provider,
lr_message_container TYPE REF TO /iwbep/if_message_container,
lr_entity_data TYPE REF TO data,
ls_context_details TYPE /iwbep/if_mgw_core_srv_runtime=>ty_s_mgw_request_context,
ls_changeset_response LIKE LINE OF ct_changeset_response.
FIELD-SYMBOLS:
<fs_ls_changeset_request> LIKE LINE OF it_changeset_request.
LOOP AT it_changeset_request ASSIGNING <fs_ls_changeset_request>.
lr_context ?= <fs_ls_changeset_request>-request_context.
lr_entry_provider = <fs_ls_changeset_request>-entry_provider.
lr_message_container = <fs_ls_changeset_request>-msg_container.
ls_context_details = lr_context->get_request_details( ).
CASE ls_context_details-target_entity.
WHEN 'SomeEntity'.
"Do the processing here
WHEN OTHERS.
ENDCASE.
ENDLOOP.
ENDMETHOD.
From the error I can tell you must be using SAP GW :-) This happens only for batch requests containing more than one create/delete/update calls and it's related to transaction security ("all or nothing"). What you have to do is redefining the corresponding GW method, I think it was CHANGESET_BEGIN. See https://archive.sap.com/discussions/thread/3562720 for some details (can't offer more for now...).

Implementing `startCursor` and `endCursor` in Relay

We have a graphql server not written in javascript, which we're trying to conform to the relay specification. startCursor and endCursor show up in a few examples but not in any official docs; based on my reading of https://github.com/facebook/relay/issues/372 those fields are basically deprecated, but they do show up in some code still. Do we have to implement them:
to be spec compliant?
to work with existing clients?
to be spec compliant?
As you point out, these fields don't appear in the spec, so they must not be required to conform to the spec. I conclude this because I think that's the only conclusion any serious authors of a spec should want you to draw from the absence of something from their spec.
to work with existing clients?
This, of course, is a different, more practical question :). The only client that I am aware of that uses the Connection spec is Relay, and Relay Modern requires these fields. Since these values are used by the PaginationContainer, the Relay Modern compiler requires them on any field marked with the #connection directive:
[END_CURSOR, HAS_NEXT_PAGE, HAS_PREV_PAGE, START_CURSOR].forEach(
fieldName => {
const pageInfoField = pageInfoType.getFields()[fieldName];
invariant(
pageInfoField &&
SchemaUtils.getNullableType(pageInfoField.type) instanceof
GraphQLScalarType,
'RelayConnectionTransform: Expected type `%s` to have an ' +
'%s field for which the type is an scalar in document `%s`.',
pageInfo.type,
fieldName,
definitionName,
);
}
);
I never remember which of endCursor and startCursor corresponds to which pagination direction. Since they are not documented in the spec, you can look to graphql-relay-js for this information:
startCursor: {
type: GraphQLString,
description: 'When paginating backwards, the cursor to continue.'
},
endCursor: {
type: GraphQLString,
description: 'When paginating forwards, the cursor to continue.'
},
No, they're not deprecated, and they do show up in the docs. What that issue says is that you don't have to implement them if you don't want to use them directly in your app, because Relay is going to query the cursor for each edge in a connection automatically, and will use that when making requests during pagination.

Resources