Ограничительный ACL для торговой сети в Hyperledger Composer - PullRequest
0 голосов
/ 27 апреля 2018

Я не мог решить свою проблему, поэтому я пытаюсь объяснить это снова: Есть 2 участника (провайдер). У них обоих есть собственный кошелек и аккаунт, и они хотят обменять наличные на токены или наоборот. Они должны иметь только READ-доступ к своим собственным ресурсам из-за мошенничества, безопасности и т. Д. Но для транзакций им необходим UPDATE-доступ. Вот мой код:

org.acme.biznet.cto:

namespace org.acme.biznet

abstract participant Member identified by memberId {
o String memberId
o String name
o String email
}
// Sensorbesitzer, z.B private Personen, Haushalte etc.
participant Provider identified by providerId extends Member {
o String providerId
--> SDTWallet sdtWallet
--> Account account
}
// SDT Token Wallet von den Netzwerkteilnehmern.
asset SDTWallet identified by sdtWalletId {
o String sdtWalletId
o Double balance default = 0.0 
--> Member owner 
}
// Geldkonto von den Netzwerkteilnehmern.
asset Account identified by accountId {
o String accountId
o Double balance default = 0.0
--> Member owner 
}
// Cash gegen Tokens getauscht.
transaction TradeCashToTokens {
o Double cashRate default = 2.0
o Double cashValue default = 1.0 range = [1.0,]
--> SDTWallet fromSDT 
--> SDTWallet toSDT
--> Account fromCash
--> Account toCash
}
// Tokens gegen Cash getauscht.
transaction TradeTokensToCash {
o Double tokenRate default = 0.5       
o Double tokenValue default = 2.0 range = [2.0,]    
--> SDTWallet fromSDT
--> SDTWallet toSDT
--> Account fromCash
--> Account toCash
}

и logic.js:

/**
* Cash to tokens transaction
* @param {org.acme.biznet.TradeCashToTokens} UpdateValues
 * @transaction
*/
function TradeCashToTokens(UpdateValues) {

//determine change in tokens value from the rate
var tokensChange = (UpdateValues.cashRate * UpdateValues.cashValue);

if(UpdateValues.fromCash.balance < UpdateValues.cashValue) {
    throw new Error('Insufficient cash funds!');
} else if (tokensChange > UpdateValues.fromSDT.balance) {
    throw new Error('Not enough tokens for this transaction!'); 
}
//alert("Fehler!");

//update values of exchanger1 cash account
console.log('#### exchanger1 cash balance before: ' + UpdateValues.fromCash.balance);
UpdateValues.fromCash.balance -= UpdateValues.cashValue;
console.log('#### exchanger1 cash balance after: ' + UpdateValues.fromCash.balance);
//update values of exchanger2 cash account
console.log('#### exchanger2 cash balance before: ' + UpdateValues.toCash.balance);
UpdateValues.toCash.balance += UpdateValues.cashValue;
console.log('#### exchanger2 cash balance after: ' + UpdateValues.toCash.balance);
//update values of exchanger1 token wallet
console.log('#### exchanger1 token balance before: ' + UpdateValues.toSDT.balance);
UpdateValues.toSDT.balance += tokensChange;
console.log('#### exchanger1 token balance after: ' + UpdateValues.toSDT.balance);
//update values of exchanger2 token wallet
console.log('#### exchanger2 token balance before: ' + UpdateValues.fromSDT.balance);
UpdateValues.fromSDT.balance -= tokensChange;
console.log('#### exchanger2 token balance after: ' + UpdateValues.fromSDT.balance);

console.log(UpdateValues.cashValue + ' EUR exchanged to ' + tokensChange + ' SDT Tokens with actual rate of ' + UpdateValues.cashRate);

return getAssetRegistry('org.acme.biznet.SDTWallet')
    .then(function (assetRegistry) {
        return assetRegistry.updateAll([UpdateValues.toSDT,UpdateValues.fromSDT]);
    })                
    .then(function () {
        return  getAssetRegistry('org.acme.biznet.Account')
        .then(function (assetRegistry) {
            return assetRegistry.updateAll([UpdateValues.toCash,UpdateValues.fromCash]); 
        });            
    });     
}

и permissions.acl:

//****************PROVIDER_PARTICIPANTS**********************

//Provider has access only to their own profile
rule ProviderAccessOwnProfile {
description: "Allow providers to access only their profile"
participant(p): "org.acme.biznet.Provider"
operation: READ, UPDATE
resource(r): "org.acme.biznet.Provider"
condition: (r.getIdentifier() === p.getIdentifier())
action: ALLOW
}

//Provider has read only access to other Providers
rule ProviderReadAccessProviders {
description: "Allow provider read access to other providers"
participant: "org.acme.biznet.Provider"
operation: READ
resource: "org.acme.biznet.Provider"
action: ALLOW
}

//****************PROVIDER_ASSETS**********************

rule ProvidersReadAccesstoAccount {
description: "Traders see their own BankAccount only"
participant: "org.acme.biznet.Provider"
operation: READ
resource: "org.acme.biznet.Account"
action: ALLOW
}

rule ProvidersReadAccesstoSDTWallet {
description: "Providers see their own SDT Wallet only"
participant: "org.acme.biznet.Provider"
operation: READ
resource: "org.acme.biznet.SDTWallet"
action: ALLOW
}

//Provider can submit CashToToken transaction
rule ProvidercanUpdateAccountthroughTransactionOnly {
        description: "Allow trader to submit trade transactions"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.Account"
        transaction(tx): "org.acme.biznet.TradeCashToTokens"
        condition: (p.getIdentifier() === r.owner.getIdentifier() && 
r.getIdentifier() === tx.toCash.getIdentifier())
        action: ALLOW
}

//Provider can submit CashToToken transaction
rule ProvidercanUpdateSDTWalletthroughTransactionOnly {
        description: "Allow trader to submit trade transactions"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.SDTWallet"
        transaction(tx): "org.acme.biznet.TradeCashToTokens"
        condition: (p.getIdentifier() === r.owner.getIdentifier() && 
 r.getIdentifier() === tx.fromSDT.getIdentifier())
        action: ALLOW
 }


//****************PROVIDER_TRANSACTIONS**********************

//Provider can submit CashToTokens transaction
rule ProviderSubmitCashToTokenTransactions {
description: "Allow provider to submit cash to tokens transactions"
participant: "org.acme.biznet.Provider"
operation: CREATE, READ
resource: "org.acme.biznet.TradeCashToTokens"
action: ALLOW
}

//Provider can submit TokenToCash transaction
rule ProviderSubmitTokensToCashTransactions {
description: "Allow provider to submit tokens to cash transactions"
participant: "org.acme.biznet.Provider"
operation: CREATE, READ
resource: "org.acme.biznet.TradeTokensToCash"
action: ALLOW
}

//****************PROVIDER_HISTORY**********************

//Provider can see the history of own transactions only
rule ProviderSeeOwnHistoryOnly {
description: "Proviers should be able to see the history of their own 
transactions only"
participant(p): "org.acme.biznet.Provider"
operation: READ
resource(r): "org.hyperledger.composer.system.HistorianRecord"
condition: (r.participantInvoking.getIdentifier() != p.getIdentifier())
action: DENY
}

//*********************NETWORK***************************
rule SystemACL {
description:  "System ACL to permit all access"
participant: "org.hyperledger.composer.system.Participant"
operation: ALL
resource: "org.hyperledger.composer.system.**"
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
}

И когда я хочу попробовать совершить транзакцию в качестве провайдера, например, TradeCachToTokens, это говорит t: Participant 'org.acme.biznet.Provider#P1' does not have 'UPDATE' access to resource 'org.acme.biznet.SDTWallet#SDT1'

см. Скриншот: cash_to_tokens

Провайдер (P1) должен получить UPDATE-доступ для Кошелька и Аккаунта, если он совершает транзакцию, но не только свою собственную, для своей противоположности (P2).

В чем здесь проблема?

1 Ответ

0 голосов
/ 27 апреля 2018

ОБНОВЛЕННЫЙ ОТВЕТ: ответ (10 мая):

  1. Вы обновляете реестры org.acme.biznet.SDTWallet и org.acme.bixnet.Account - и я вижу, что у вас есть правила, позволяющие выполнять обновления из транзакции TradeCashToTokens или даже TradeTokensToCash. Я думаю, что проблема заключается в условии должно быть || а не && - оценивается один ресурс за раз, и владелец ресурса может быть ИСТИНА в условном совпадении. Поскольку trxn вызывается участником, он всегда должен оценивать TRUE (если он, конечно, не является владельцем ресурса), часть A условия; для целевого ресурса (toCash или toSDT) вы сравниваете его с владельцем ресурса (обновляется в коде функции транзакции - имена указаны выше). Обратите внимание, что правила основаны на том, что вызывающий участник обновляет 2 целевых ресурса (в зависимости от участника, а не от учетной записи - ps. Думаю, причина, по которой ваше правило «SDT» не сработало, заключается в том, что правило говорит «fromSDT» (оценивается только для одного целевого ресурса).

    Предложите набор правил, таких как:

    
    
    rule UpdateAccountsviaTradeCashToTokens {
        description: "Allow source/target providers defined in trxn (ie 2)- to access/update their Accounts from, trxn TradeCashToTokens only"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.Account"
        transaction(tx): "org.acme.biznet.TradeCashToTokens"
        condition: ( p.getIdentifier() === r.owner.getIdentifier() || tx.toCash.owner.getIdentifier()  === r.owner.getIdentifier() )
        action: ALLOW
    }
    
    
    rule UpdateSDTWalletsviaTradeCashToTokens {
        description: "Allow source/target providers defined in trxn (ie 2)- to access/update their SDT Wallets from, trxn TradeCashToTokens only"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.SDTWallet"
        transaction(tx): "org.acme.biznet.TradeCashToTokens"
        condition: ( p.getIdentifier() === r.owner.getIdentifier() || tx.toSDT.owner.getIdentifier()  === r.owner.getIdentifier() ) 
        action: ALLOW
    }
    
  2. Аналогично - для другой транзакции TradeTokenstoCash вы можете иметь

    
    rule UpdateAccountsviaTradeTokensToCash {
        description: "Allow source/target providers defined in trxn (ie 2)- to access/update their Accounts from, trxn TradeTokensToCash only"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.Account"
        transaction(tx): "org.acme.biznet.TradeTokensToCash"
        condition: ( p.getIdentifier() === r.owner.getIdentifier() || tx.toCash.owner.getIdentifier()  === r.owner.getIdentifier() )
        action: ALLOW
    }
    
    rule UpdateSDTWalletsviaTradeTokenstoCash {
        description: "Allow source/target providers defined in trxn (ie 2)- to access/update their SDT Wallets from, trxn TradeTokenstoCash only"
        participant(p): "org.acme.biznet.Provider"
        operation: READ, UPDATE
        resource(r): "org.acme.biznet.SDTWallet"
        transaction(tx): "org.acme.biznet.TradeTokenstoCash"
        condition: ( p.getIdentifier() === r.owner.getIdentifier() ||  tx.toSDT.owner.getIdentifier()  === r.owner.getIdentifier() )
        action: ALLOW
    }
    
    
    
  3. Вам по-прежнему понадобятся ваши PROVIDER_TRANSACTIONS правила.

  4. Вы правильно сказали, что вам понадобятся правила PROVIDER_ASSETS - до правил, основанных на обновлении транзакции (т.е. упомянутых выше).

  5. Я создал учебник ACL - который я со временем включу в документы Composer (для блага других) - аналогично тому, что вы сделали.

https://github.com/mahoney1/test/blob/master/acl_dynamic.md

Надеюсь, это поможет, перепробовал ваш полный набор правил с изменениями, и он работает; если вы хотите, чтобы я опубликовал полный набор правил, дайте мне знать.

...