Access Control problem in hyperledger composer for non-admin participants - hyperledger

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?

Related

Neo4j GraphQL auth directive always giving forbidden

I'm trying to implement the #auth directive in GraphQL for use with Neo4j as documented here:
https://neo4j.com/docs/graphql-manual/current/auth/auth-directive/
With a jwt token that is taken from firebase, and should have all of the necessary fields, including admin roles
The problem is that whenever I try to use one of the generated queries with the admin bearer token it says "forbidden" when the auth directive is attached to it.
The full discussion of this issue between me and ChatGPT, which includes extensive trial and error that was done before writing this question, logs, code snippets etc, can be found here for reference:
https://firebasestorage.googleapis.com/v0/b/awtsmoos.appspot.com/o/ai%2FBH_1674546675630.html?alt=media&token=17b653c4-5db2-4bca-8bc1-3cc3625e5a6c
Just to summarize some key code parts, I'm trying to follow the setup example like this essentially:
const neoSch = new graphqlNeo.Neo4jGraphQL({
typeDefs: typeDefs,
driver:dr,
resolvers:rez,
plugins: {
auth: new neoGraphQLAuth
.Neo4jGraphQLAuthJWTPlugin({
secret:
secret.private_key.toString()
})
}
})
Here's the schema that it suggested after I gave it some samples, doesn't work:
type Homework {
id: ID #id
title: String!
steps: [Step!]! #relationship(
type: "HAS",
direction: OUT
)
}
extend type Homework #auth(
rules:[
{
allow: CREATE,
roles:[
"ADMIN"
]
}
]
)
extend type Homework #auth(
rules:[
{
allow: READ,
}
]
)
The token itself is getting properly passed in, as discussed at length in the ChatGPT session, I'm not sure what else it is?
Where the secret property is my JSON of a service account taken from firebase, then in my Apollo context I've tried lots of trial and error with no success, in this matter, but here was one implantation I tried:
app.use(
"/etsem",
cors(),
bodyp.json(),
exp4.expressMiddleware(
serv, {
context: async info => {
var rz = {
req:info.req,
headers:info.req.headers
}
return rz;
}
}
)
)
But still I got the forbidden error

can't use log analytics workspace in a different subscription? terraform azurerm policy assignment

I'm using terraform to write azure policy as code
I found two problems
1 I can't seem to use log analytics workspace that is on a different subscription, within same subscription, it's fine
2 For policies that needs managed identity, I can't seem to assign correct rights to it.
resource "azurerm_policy_assignment" "Enable_Azure_Monitor_for_VMs" {
name = "Enable Azure Monitor for VMs"
scope = data.azurerm_subscription.current.id
policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/55f3eceb-5573-4f18-9695-226972c6d74a"
description = "Enable Azure Monitor for the virtual machines (VMs) in the specified scope (management group, subscription or resource group). Takes Log Analytics workspace as parameter."
display_name = "Enable Azure Monitor for VMs"
location = var.location
metadata = jsonencode(
{
"category" : "General"
})
parameters = jsonencode({
"logAnalytics_1" : {
"value" : var.log_analytics_workspace_ID
}
})
identity {
type = "SystemAssigned"
}
}
resource "azurerm_role_assignment" "vm_policy_msi_assignment" {
scope = azurerm_policy_assignment.Enable_Azure_Monitor_for_VMs.scope
role_definition_name = "Contributor"
principal_id = azurerm_policy_assignment.Enable_Azure_Monitor_for_VMs.identity[0].principal_id
}
for var.log_analytics_workspace_ID, if i use the workspace id that is in the same subscription as the policy, it would work fine. but If I use a workspace ID from a different subscription, after deployment, the workspace field will be blank.
also for
resource "azurerm_role_assignment" "vm_policy_msi_assignment"
, I have already given myself user access management role, but after deployment, "This identity currently has the following permissions:" is still blank?
I got an answer to my own question:)
1 this is not something designed well in Azure, I recon.
MS states "a Managed Identity (MSI) is created for each policy assignment that contains DeployIfNotExists effects in the definitions. The required permission for the target assignment scope is managed automatically. However, if the remediation tasks need to interact with resources outside of the assignment scope, you will need to manually configure the required permissions."
which means, the system generated managed identity which needs access in log analytics workspace in another subscription need to be manually with log analytics workspace contributor rights
Also since you can't user user generated managed ID, you can't pre-populate this.
so if you want to to achieve in terraform, it seems you have to run policy assignment twice, the first time is just to get ID, then manual ( or via script) to assign permission, then run policy assignment again to point to the resource..
2 The ID was actually given the contributor rights, you just have to go into sub RBAC to see it.

Create team from group fails with exception

I created teams in Microsoft Teams (from groups as documented here) via the C# graph-api sdk without any problems - everything was working just fine.
But suddenly this is not working anymore. I will always get the following exception at the line return await graphServiceClient.Teams.Request().AddAsync(team);:
Message: Failed to execute Templates backend request
CreateTeamFromGroupWithTemplateRequest. Request Url:
https://teams.microsoft.com/fabric/emea/templates/api/groups/theGroupId/team,
Request Method: PUT,
And further:
Team Visibility can not be specified as it is inherited from the
group.
I know that the visibility property must not be set if creating the team from a group as it states in the Microsoft documentation:
The team that's created will always inherit from the group's display name, visibility, specialization, and members. Therefore, when making this call with the group#odata.bind property, the inclusion of team displayName, visibility, specialization, or members#odata.bind properties will return an error.
But the currently used code below shows that I am not setting any forbidden properties - and this code worked for the last few days, too:
private async Task<Team> CreateTeamFromGroup(string groupId)
{
var graphServiceClient = [...]
var groupResourceLink = $"https://graph.microsoft.com/v1.0/groups('{groupId}')";
var team = new Team
{
AdditionalData = new Dictionary<string, object>()
{
{ "template#odata.bind", "https://graph.microsoft.com/beta/teamsTemplates('standard')" },
{ "group#odata.bind", groupResourceLink }
},
Channels = new TeamChannelsCollectionPage
{
new Channel
{
DisplayName = "WhatEver"
}
}
};
return await graphServiceClient.Teams.Request().AddAsync(team);
}
Is anyone else experiencing this problem? Was there an API change? Was the teams backend changed? Anyone any ideas?
P.S.: I am using the latest NuGet-Package for Microsoft Graph - downgrading didn't help.
Update (with a not very satisfying work-around)
The error can be reproduced via the graph api explorer, too.
The POST command above issues a PUT command, that is described here. With this request, the team can be created.
The documentation and the graph api snippet for C# is out-dated, though. You have to add odatatype = null to the properties when using the sdk
Unfortunately it is not possible to add channels in the same step. If you specify the property 'channels' it will just be ignored.
Update (Detailed error message)
System.AggregateException: 'One or more errors occurred. (Code:
BadRequest Message: Failed to execute Templates backend request
CreateTeamFromGroupWithTemplateRequest. Request Url:
https://teams.microsoft.com/fabric/emea/templates/api/groups/theGroupId/team,
Request Method: PUT, Response Status Code: BadRequest,
ErrorMessage : {"errors":[{"message":"Team Visibility can not be
specified as it is inherited from the
group."}],"operationId":"639448e414ece64caee8f52839585bf7"} Inner
error: AdditionalData: date: 2020-11-24T10:21:22 request-id:
37a28cac-3ac5-4bd2-a061-daf44c442fac client-request-id:
37a28cac-3ac5-4bd2-a061-daf44c442fac ClientRequestId:
37a28cac-3ac5-4bd2-a061-daf44c442fac )'
Just tested this morning and I can say, that the "old way" by using the beta API to create a team with a template works again. Don't know, how many other ways exist to do these things, but here is our current request, that works now (again).
POST https://graph.microsoft.com/beta/teams
{
"displayName": "My Group Name",
"description": "Some description",
"template#odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('educationClass')",
"owners#odata.bind": [
"https://graph.microsoft.com/beta/users('<someValidUserId>')"
]
}
I think this will be just an intermediate state and when the bugs are fixed, they will publish the new version again and this kind of creation will fail again, but if in this case the v1.0 documented way will work this wouldn't be a big problem. But being informed BEFORE there roll-out starts would be great.
This was a Microsoft issue/ bug and is currently being fixed as stated here.

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')

Hyperledger Composer v0.19 Hiding Historian in ACL

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.

Resources