I am trying to use BusinessNetworkConnection for NodeJS, but how do I get the credentials from a deployed BNA on playground and save it in my server directory?
I am getting
2017-11-03T13:07:32.83-0400 [APP/PROC/WEB/0] ERR (node:62)
UnhandledPromiseRejectionWarning: Unhandled promise rejection
(rejection id: 1): Error: Error trying login and get user Context.
Error: Error trying to enroll user or load channel configuration.
Error: Enrollment failed with errors
[[{"code":400,"message":"Authorization failure"}]]
when I try using the code
const BusinessNetworkConnection = require("composer-client").BusinessNetworkConnection;
this.businessNetworkConnection = new BusinessNetworkConnection();
this.CONNECTION_PROFILE_NAME = "ibm-bc-org1";
this.businessNetworkIdentifier = "giveback";
this.businessNetworkConnection
.connect(
this.CONNECTION_PROFILE_NAME,
this.businessNetworkIdentifier,
"admin",
"adminpw"
)
.then(result => {
this.businessNetworkDefinition = result;
console.log("BusinessNetworkConnection: ", result);
})
I have a directory /home/vcap/app/.composer-connection-profiles/ibm-bc-org1 with a connection.json file that references /home/vcap/app/.composer-credentials/ibm-bc-org1 for my credentials. The code worked for composer#0.13.2 but now I moved over to composer#0.14.3. I removed the previous credentials and created a new playground etc, everything is fresh and clean.
There is a work around when something like this happens. Because I am trying to connect with the credentials that Composer created the with admin || adminpw. You can just define a new participant in your model file and then give that participant system permissions to query and listen for events that the Historian emits.
For example in your model.cto:
participant ServerAdmin identified by serverhash {
// ServerAdmin is a type of participant
o String serverhash
}
And in your permissions.acl add :
rule ServerAdminUser {
description: "Grant business network administrators full access to
user resources"
participant: "org.acme.sample.ServerAdmin"
operation: ALL
resource: "**"
action: ALLOW
}
rule ServerAdminSystem {
description: "Grant business network administrators full access to system resources"
participant: "org.acme.sample.ServerAdmin"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}
Then after the network has been deployed by Composer on playground, you can add this participant VIA the REST API, and issue it a new identity. This will give you a User ID and User Secret with which you can use in BusinessNetworkConnection.connect()
Related
I want to run a google analytics report using runReport.
I have followed the instructions at https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries and made a copy of the code that uses json-credentials at https://github.com/googleapis/nodejs-analytics-data/blob/main/samples/quickstart_json_credentials.js
I have one Analytics Account with two Properties & Apps - DEV and STAGE.
In each of them I have created a service account with OWNER permissions. After that I created a key and downloaded the generated JSON-file.
I can test and run the API from the "Try this API" link at https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport for both my properties and it works well for both of them. (But then I use OAuth authentication of course).
However when I run the code using the JSON-credentials the DEV always work. The STAGE always fails. I have tried running the code both from my machine as well as from https://shell.cloud.google.com/ with the same result.
The failure message is:
7 PERMISSION_DENIED: User does not have sufficient permissions for this property. To learn more about Property ID, see https://developers.google.com/analytics/devguides/reporting/data/v1/property-id.
I have checked several times that the DEV and STAGE properties are correct and that the I use the JSON-credentials file associated with the correct property.
In STAGE, where calls always fail I have several times created new service accounts (with Basic->Owner credentials), created keys and downloaded JSON-credentials. But all with the same result. STAGE always fails.
I have compared the permissions for the service accounts in DEV and STAGE and they seems to be identical.
I have read and tried tips from other people with "permission denied" issues here at stack overflow but none that solves my issue.
Are there any authorization logs that I read from google console?
I'm kind of stuck now.
The code I run (properties and file name obfuscated):
"use strict";
function main(propertyId = "YOUR-GA4-PROPERTY-ID", credentialsJsonPath = "") {
propertyId = "27..DEV property";
credentialsJsonPath = "./DEVcredentials.json";
// propertyId = "27..STAGE property";
// credentialsJsonPath = "./STAGEcredentials.json";
const { BetaAnalyticsDataClient } = require("#google-analytics/data");
const analyticsDataClient = new BetaAnalyticsDataClient({
keyFilename: credentialsJsonPath,
});
async function runReport() {
const [response] = await analyticsDataClient.runReport({
property: `properties/${propertyId}`,
dateRanges: [
{
startDate: "2020-03-31",
endDate: "today",
},
],
dimensions: [
{
name: "country",
},
],
metrics: [
{
name: "activeUsers",
},
],
});
console.log("Report result:");
response.rows.forEach((row) => {
console.log(row.dimensionValues[0], row.metricValues[0]);
});
}
runReport();
}
process.on("unhandledRejection", (err) => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
User does not have sufficient permissions for this property.
Means that the user who you have authenticated with does not have permissions to access that view. In this case we are talking about properties/${propertyId}
If you are using a service account make sure to grant it permissions at the account level not the view level.
Permissions need to be granted thorough the google analytics website in the admin section
I was trying to authenticate to Azure DefaultAzureCredential using #azure/identity in Node js to get the reports of Azure API Management Service.
Things I have done :
Created An API Management Service from Azure Portal
Registered an application with Azure AD and create a service principal using this documentation.
I Have configured environment variables correctly to use DefaultAzureCredential as mentioned in this documentation.
AZURE_TENANT_ID,
AZURE_CLIENT_ID,
AZURE_CLIENT_SECRET,
AZURE_SUBSCRIPTION,
But the authentication is getting failed and I am not able to generate credentials. when I consoled the new DefaultAzureCredential(); response, it says that UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials',
require("dotenv").config();
const { DefaultAzureCredential } = require("#azure/identity");
const { ApiManagementClient } = require("#azure/arm-apimanagement");
if (!process.env.AZURE_TENANT_ID) throw Error("AZURE_TENANT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_ID) throw Error("AZURE_CLIENT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_SECRET) throw Error("AZURE_CLIENT_SECRET is missing from environment variables.");
if (!process.env.AZURE_RESOURCE_GROUP) throw Error("AZURE_RESOURCE_GROUP is missing from environment variables.");
if (!process.env.AZURE_SERVICE_NAME) throw Error("AZURE_SERVICE_NAME is missing from environment variables.");
if (!process.env.AZURE_SUBSCRIPTION) throw Error("AZURE_SUBSCRIPTION is missing from environment variables.");
const subscriptionId = process.env.AZURE_SUBSCRIPTION;
const credentials = new DefaultAzureCredential();
console.log(credentials);
And I got this Error,
DefaultAzureCredential {
UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials',
_sources: [
EnvironmentCredential { _credential: [ClientSecretCredential] },
ManagedIdentityCredential {
isEndpointUnavailable: null,
clientId: 'c8xxxxxxxx5ac8',
identityClient: [IdentityClient]
},
AzureCliCredential {},
VisualStudioCodeCredential {
cloudName: 'AzureCloud',
identityClient: [IdentityClient],
tenantId: 'common'
}
]
}
As one of the answer to a similar question in stack overflow mentioned that The DefaultAzureCredential works even though it shows the unavailable message,
I tried moving on to getting reports of an API Management Service using #azure/identity
const client = new ApiManagementClient(credentials, subscriptionId);
const resourceGroupName = process.env.AZURE_RESOURCE_GROUP;
const serviceName = process.env.AZURE_SERVICE_NAME;
const filter = "callCountSuccess";
client.reports
.listBySubscription(
resourceGroupName,
serviceName,
filter
)
.then((result) => {
console.log(JSON.stringify(result));
})
.catch((err) => {
console.log(err);
});
But as this is also giving the 403 error,
response: {
body: `{"error":
{"code":"AuthorizationFailed",
"message":
"The client 'cxxxxxxxxxxxxxxx569' with object id 'cxxxxxxxxxxxxxxx569'
does not have authorization to perform action 'Microsoft.ApiManagement/service/reports/read'
over scope '/subscriptions/85xxxxxxx3c5/resourceGroups/axxxb/providers/Microsoft.ApiManagement/service/Axxxx/reports/bySubscription'
or the scope is invalid.
If access was recently granted, please refresh your credentials."}}`,
headers: HttpHeaders { _headersMap: [Object] },
status: 403
},
EDIT
I have added the API Management Sevice Reader Role to The Api management service but I am getting the same error as above.
The reason you are running into AuthorizationFailed error is because it looks like you have not assigned any permissions (RBAC role) to your Service Principal.
By default, the Service Principal will not have any permissions to perform operations on an Azure Subscription. You will need to grant appropriate permissions explicitly by assigning suitable RBAC role to your Service Principal.
You can try by assigning Reader role to your Service Principal at Subscription, Resource Group or API Management resource level. You may find this link helpful: https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-steps.
Once appropriate role has been assigned, you should not get this error.
I am trying to issue a new identity to a participant, create a composer card and import it.
My base.cto file is
namespace com.algorythmix.base
participant Department identified by departmentId {
o String departmentId
}
My function to issue an identity
const initIdentities = () => {
return new Promise(async function(resolve, reject) {
try {
const businessNetworkConnection = new BusinessNetworkConnection();
await businessNetworkConnection.connect(adminCardName);
let departmentRegistry = await businessNetworkConnection.getParticipantRegistry(`${BASE_NS}.Department`);
let departmentOne = await departmentRegistry.get('departmentOne');
let deptOne = await businessNetworkConnection.issueIdentity(`${BASE_NS}.Department#${departmentOne.departmentId}`, 'departmentOne');
console.log(`userID = ${deptOne.userID}`);
console.log(`userSecret = ${deptOne.userSecret}`);
let departmentTwo = await departmentRegistry.get('departmentTwo');
let deptTwo = await businessNetworkConnection.issueIdentity(`${BASE_NS}.Department#${departmentTwo.departmentId}`, 'departmentTwo');
console.log(`userID = ${deptTwo.userID}`);
console.log(`userSecret = ${deptTwo.userSecret}`);
const adminConnection = new AdminConnection(); // { cardStore: $SOME_PATH_VARIABLE } to change def2ault card storage path
await adminConnection.connect(adminCardName); // Confirm this
console.log('connected');
const cardOne = new IdCard({
userName: 'departmentOne',
version: 1,
enrollmentSecret: deptOne.userSecret,
businessNetwork: 'chips'
}, connectionProfile);
const cardTwo = new IdCard({
userName: 'departmentTwo',
version: 1,
enrollmentSecret: deptTwo.userSecret,
businessNetwork: 'chips'
}, connectionProfile);
console.log('importing card one');
await adminConnection.importCard('departmentOne', cardOne);
await adminConnection.importCard('departmentTwo', cardTwo);
console.log('imported card two');
await businessNetworkConnection.disconnect();
await adminConnection.disconnect();
resolve();
} catch (e) {
reject(e);
};
});
};
Where adminCardName is the one generated when using composer network start command as per the basic tutorial provided here https://hyperledger.github.io/composer/latest/tutorials/deploy-to-fabric-single-org
And connectionProfile is taken from the above page as well. I have double checked the connection profile used by the admin#chips card and the one I have used is exactly the same.
Once I run the function, in composer card list, a card called departmentOne and departmentTwo is listed with the Business network shown as chips (as expected).
Now when I run composer network ping -c departmentOne, I get the error
Error: 2 UNKNOWN: error executing chaincode: transaction returned with failure: AccessException: Participant 'com.algorythmix.base.Department#departmentOne' does not have 'READ' access to resource 'org.hyperledger.composer.system.Network#chips#0.2.0'
Command failed
I have
1) Deleted permissions.acl which as per the documentation results in everyone getting full access
2) used following permissions.acl file
rule Default {
description: "Allow all participants access to all resources"
participant: "com.algorythmix.base.Department"
operation: ALL
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
}
To specifically give the participant access to the network. I have also uploaded the .bna to composer-playground and it works over there as expected.
Can someone please guide me, as to what I am doing wrong?
Info:
Ubuntu - 16.0.4
Fabric - 1.1
Composer - 0.19.11
Node - 8.9.1
the error 'org.hyperledger.composer.system.Network#chips#0.2.0' suggests the underlying participant does not have the minimal READ access to the actual business network.
I would suggest a rule (rule 2) something like this:
rule ReadNetwork {
description: "Allow all participants to read network"
participant: "org.hyperledger.composer.system.Participant"
operation: READ
resource: "org.hyperledger.composer.system.Network"
action: ALLOW
}
I solved the same issue by changing the version in package.json file.
I am working in a proof of concept with a Node.js application and 'composer-client' npm module.
I have tried different commands such as adding a participant, adding an asset and performing a transaction and everything seems to work correctly.
However, when I try to issue a new identity I do not get the results that I expect. I execute my Node.js application with the following code:
var businessNetwork = new BusinessNetworkConnection();
return businessNetwork.connect('admin#tutorial-network')
.then(() => {
return businessNetwork.issueIdentity('org.acme.biznet.Trader#Trader_001', 'usr001')
})
.then((result) => {
console.log(`userID = ${result.userID}`);
console.log(`userSecret = ${result.userSecret}`);
})
.catch((error) => {
console.error(error);
});
Then, UserId and UserSecret are displayed at console log. After that, I try to do a ping to Business Network:
var businessNetwork = new BusinessNetworkConnection();
return businessNetwork.connect('usr001#tutorial-network')
.then(() => {
return businessNetwork.ping();
})
.then((result) => {
console.log(`participant = ${result.participant ? result.participant : '<no participant found>'}`);
})
.catch((error) => {
console.error(error);
});
However, I get the following error message:
{ Error: Card not found: usr001#tutorial-network
at IdCard.fromDirectory.catch.cause (/home/user.name/git_repositories/nodejs/first.blockchain.test/node_modules/composer-common/lib/cardstore/filesystemcardstore.js:73:27)
at <anonymous>
cause:
{ Error: Unable to read card directory: /home/user.name/.composer/cards/user001#tutorial-network
If I execute the command composer identity list -c admin#tutorial-network, I get the following output:
$class: org.hyperledger.composer.system.Identity
identityId: 9b49f67c262c0ae23e1e0c4a8dc61c4a12b5119df2b6a49fa2e02fa56b8818c3
name: usr001
issuer: 27c582d674ddf0f230854814b7cfd04553f3d0eac55e37d915386c614a5a1de9
certificate:
state: ISSUED
participant: resource:org.acme.biznet.Trader#Trader_001
But, I am not able to find the business card.
It works for me. I'm using composer 0.15.1.
var businessNetwork = new BusinessNetworkConnection();
return businessNetwork.connect('admin#carauction-network')
.then(() => {
return businessNetwork.ping();
})
.then((result) => {
console.log(`participant = ${result.participant ? result.participant : '<no participant found>'}`);
})
.catch((error) => {
console.error(error);
});
Output is like this
linux1#fabric:~/eventclient$ node event.js
participant = org.hyperledger.composer.system.NetworkAdmin#admin
You may need to import ID card to wallet ?
composer card import --file networkadmin.card
I had a similar issue late last week. Part of the upgrade instructions from V0.14 to V0.15 states that we have to delete the (if existing) ~/.composer, ~/.composer-connection-profiles and ~/.composer-credentials. I skipped that step on my first upgrade to v01.5 and encountered the error you are seeing. Went back and deleted those three folders, reinstalled the binaries and rechecked docker image status. Error went away and has not reappeared.
You named the new card user001, not user001##tutorial-network. Try connecting with just user001 as your connection card name.
I used the following command to create a card for the participant using the enrollment secret obtained from the javascript.
composer card create -u usr001 -s <enrollment_secret> -f usr001.card -n tutorial-network -p connection.json
You probably created the connection.json needed in some step before in the tutorial you are following. If this file is not available explicitly, you may get it from the composer wallet. In the current version, it can be located in /home/your_user/.composer/cards/. If you are only following the tutorial, any connection.json in this directory will do.
After that, you must add the credential created to the wallet using:
composer card import -f usr001.card
Your code for testing the issued identity is correct.
Am using the node.js SDK to call the Azure notification hub api, I registered an application using Azure Active directory also i created a resource group and added my user to it as owner. But am getting this error when calling the api:
AuthorizationFailed
The client '333848ca-f996-XXXXXXXXXXXX' with object id
'333848ca-f996-XXXXXXXXX' does not have authorization to perform
action 'Microsoft.NotificationHubs/namespaces/write' over scope
'/subscriptions/ef8e8e-XXXXXXXXXXXX/resourceGroups/notificationGroup/providers/Microsoft.NotificationHubs/namespaces/namespaceapp1
The code:
MsRest.loginWithServicePrincipalSecret(
My Subscription ID,
My Application Secret Key,
My Directory ID, // found under AD -> properties
(err, credentials) => {
if (err) throw err;
// eslint-disable-next-line
const client = new notificationHubsClient(credentials, AZURE_SUBSCRIPTION_ID);
const createNamespaceParameters = {
location: AZURE_LOCATION,
tags: {
tag1: 'value1',
tag2: 'value2',
},
};
client.namespaces.createOrUpdate(AZURE_RESOURCE_GROUP_NAME, req.body.name, createNamespaceParameters,
(error, result) => {
if (error) {
res.send(error);
}
console.info(`Namespace created${JSON.stringify(result, null, ' ')}`);
res.send('app created');
});
},
);
According to the error message, you'll need to add your Azure Active directory application to the Contributor role for creating the namespace in Azure Notification Hub.
You can follow the steps below which are also documented here.
Go to Azure portal and select Subscriptions.
Select the particular subscription (resource group or resource) to assign the application to.
Select Access Control (IAM).
Select Add.
Select the Contributor role to assign to your AAD application.