Skip to content

Commit 87f6277

Browse files
tleacmcsacecillerestyled-commitstcarmelveilleux
authored
Managed ACL: Add AccessRestrictionList support (#34932)
* Add AccessRestrictionList support * Update src/access/AccessConfig.h Co-authored-by: C Freeman <cecille@google.com> * Reworked data manipulators and other cleanup * Fixed encode/decode so reading CommissioningARL and Arl attributes work * Reworked ARL storage Previously ARL related data was persisted in KVS. This has been removed and now the responsibility for managing/maintaining the related data (CommissioningARL and ARL attributes) is up to the app to set on AccessRestrictionProvider class. * Review fixes cleanup ArlEncoder interface. return error to client if arl review request fails return token to client in FabricRestrictionReviewUpdate * Fixed GetEntries vector pointer arg * Updated core restriction logic/integration * Restyled by clang-format * fixed include check for renamed AccessRestrictionProvider.h file * M-ACL updates - refactored AccessControl::Check into CheckACL and CheckARL - added placeholders for the upcoming CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL - extracted ARL exception processing to standalone class for better testing * Add plumbing for subject descriptor IsCommissioning field - Make session manager update that state on a message-per-message basis - Add tests Missing test: MRP test against a not-yet-committed fabric over CASE showing that IsCommissioning is true. * Fix crash * Use new IsCommissioning in ARL check * Updates for review comments * restyled * Review updates - fixed return type for some command failures - enhanced unit tests * restyled * Updated ARL tests per review comments * work around nuttx and jsoncpp contention * Review comments and nuttx build failure fix attempt * review updates --------- Co-authored-by: C Freeman <cecille@google.com> Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: tennessee.carmelveilleux@gmail.com <tennessee.carmelveilleux@gmail.com>
1 parent 32c961f commit 87f6277

40 files changed

+2349
-63
lines changed

examples/network-manager-app/linux/args.gni

+3
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ chip_project_config_include_dirs = [
2222
]
2323

2424
chip_config_network_layer_ble = false
25+
26+
# This enables AccessRestrictionList (ARL) support used by the NIM sample app
27+
chip_enable_access_restrictions = true

examples/network-manager-app/network-manager-common/network-manager-app.matter

+8-1
Original file line numberDiff line numberDiff line change
@@ -1623,16 +1623,23 @@ endpoint 0 {
16231623
server cluster AccessControl {
16241624
emits event AccessControlEntryChanged;
16251625
emits event AccessControlExtensionChanged;
1626+
emits event AccessRestrictionEntryChanged;
1627+
emits event FabricRestrictionReviewUpdate;
16261628
callback attribute acl;
16271629
callback attribute extension;
16281630
callback attribute subjectsPerAccessControlEntry;
16291631
callback attribute targetsPerAccessControlEntry;
16301632
callback attribute accessControlEntriesPerFabric;
1633+
callback attribute commissioningARL;
1634+
callback attribute arl;
16311635
callback attribute generatedCommandList;
16321636
callback attribute acceptedCommandList;
16331637
callback attribute attributeList;
1634-
ram attribute featureMap default = 0;
1638+
ram attribute featureMap default = 1;
16351639
callback attribute clusterRevision;
1640+
1641+
handle command ReviewFabricRestrictions;
1642+
handle command ReviewFabricRestrictionsResponse;
16361643
}
16371644

16381645
server cluster BasicInformation {

examples/network-manager-app/network-manager-common/network-manager-app.zap

+65-1
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,24 @@
314314
"define": "ACCESS_CONTROL_CLUSTER",
315315
"side": "server",
316316
"enabled": 1,
317+
"commands": [
318+
{
319+
"name": "ReviewFabricRestrictions",
320+
"code": 0,
321+
"mfgCode": null,
322+
"source": "client",
323+
"isIncoming": 1,
324+
"isEnabled": 1
325+
},
326+
{
327+
"name": "ReviewFabricRestrictionsResponse",
328+
"code": 1,
329+
"mfgCode": null,
330+
"source": "server",
331+
"isIncoming": 0,
332+
"isEnabled": 1
333+
}
334+
],
317335
"attributes": [
318336
{
319337
"name": "ACL",
@@ -395,6 +413,38 @@
395413
"maxInterval": 65534,
396414
"reportableChange": 0
397415
},
416+
{
417+
"name": "CommissioningARL",
418+
"code": 5,
419+
"mfgCode": null,
420+
"side": "server",
421+
"type": "array",
422+
"included": 1,
423+
"storageOption": "External",
424+
"singleton": 0,
425+
"bounded": 0,
426+
"defaultValue": null,
427+
"reportable": 1,
428+
"minInterval": 1,
429+
"maxInterval": 65534,
430+
"reportableChange": 0
431+
},
432+
{
433+
"name": "ARL",
434+
"code": 6,
435+
"mfgCode": null,
436+
"side": "server",
437+
"type": "array",
438+
"included": 1,
439+
"storageOption": "External",
440+
"singleton": 0,
441+
"bounded": 0,
442+
"defaultValue": "",
443+
"reportable": 1,
444+
"minInterval": 1,
445+
"maxInterval": 65534,
446+
"reportableChange": 0
447+
},
398448
{
399449
"name": "GeneratedCommandList",
400450
"code": 65528,
@@ -453,7 +503,7 @@
453503
"storageOption": "RAM",
454504
"singleton": 0,
455505
"bounded": 0,
456-
"defaultValue": "0",
506+
"defaultValue": "1",
457507
"reportable": 1,
458508
"minInterval": 1,
459509
"maxInterval": 65534,
@@ -490,6 +540,20 @@
490540
"mfgCode": null,
491541
"side": "server",
492542
"included": 1
543+
},
544+
{
545+
"name": "AccessRestrictionEntryChanged",
546+
"code": 2,
547+
"mfgCode": null,
548+
"side": "server",
549+
"included": 1
550+
},
551+
{
552+
"name": "FabricRestrictionReviewUpdate",
553+
"code": 3,
554+
"mfgCode": null,
555+
"side": "server",
556+
"included": 1
493557
}
494558
]
495559
},

examples/platform/linux/AppMain.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@
103103
#include "AppMain.h"
104104
#include "CommissionableInit.h"
105105

106+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
107+
#include "ExampleAccessRestrictionProvider.h"
108+
#endif
109+
106110
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
107111
#include <platform/Darwin/NetworkCommissioningDriver.h>
108112
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
@@ -121,6 +125,7 @@ using namespace chip::DeviceLayer;
121125
using namespace chip::Inet;
122126
using namespace chip::Transport;
123127
using namespace chip::app::Clusters;
128+
using namespace chip::Access;
124129

125130
// Network comissioning implementation
126131
namespace {
@@ -180,6 +185,10 @@ Optional<app::Clusters::NetworkCommissioning::Instance> sWiFiNetworkCommissionin
180185
app::Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(kRootEndpointId, &sEthernetDriver);
181186
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
182187

188+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
189+
auto exampleAccessRestrictionProvider = std::make_unique<ExampleAccessRestrictionProvider>();
190+
#endif
191+
183192
void EnableThreadNetworkCommissioning()
184193
{
185194
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
@@ -593,9 +602,27 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl)
593602
chip::app::RuntimeOptionsProvider::Instance().SetSimulateNoInternalTime(
594603
LinuxDeviceOptions::GetInstance().mSimulateNoInternalTime);
595604

605+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
606+
initParams.accessRestrictionProvider = exampleAccessRestrictionProvider.get();
607+
#endif
608+
596609
// Init ZCL Data Model and CHIP App Server
597610
Server::GetInstance().Init(initParams);
598611

612+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
613+
if (LinuxDeviceOptions::GetInstance().commissioningArlEntries.HasValue())
614+
{
615+
exampleAccessRestrictionProvider->SetCommissioningEntries(
616+
LinuxDeviceOptions::GetInstance().commissioningArlEntries.Value());
617+
}
618+
619+
if (LinuxDeviceOptions::GetInstance().arlEntries.HasValue())
620+
{
621+
// This example use of the ARL feature proactively installs the provided entries on fabric index 1
622+
exampleAccessRestrictionProvider->SetEntries(1, LinuxDeviceOptions::GetInstance().arlEntries.Value());
623+
}
624+
#endif
625+
599626
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
600627
// Set ReadHandler Capacity for Subscriptions
601628
chip::app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForSubscriptions(

examples/platform/linux/BUILD.gn

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import("${chip_root}/src/lib/core/core.gni")
1919
import("${chip_root}/src/lib/lib.gni")
2020
import("${chip_root}/src/tracing/tracing_args.gni")
2121

22+
if (current_os != "nuttx") {
23+
import("//build_overrides/jsoncpp.gni")
24+
}
25+
2226
declare_args() {
2327
chip_enable_smoke_co_trigger = false
2428
chip_enable_boolean_state_configuration_trigger = false
@@ -101,6 +105,10 @@ source_set("app-main") {
101105
"${chip_root}/src/app/server",
102106
]
103107

108+
if (current_os != "nuttx") {
109+
public_deps += [ jsoncpp_root ]
110+
}
111+
104112
if (chip_enable_pw_rpc) {
105113
defines += [ "PW_RPC_ENABLED" ]
106114
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/*
20+
* AccessRestriction implementation for Linux examples.
21+
*/
22+
23+
#pragma once
24+
25+
#include <access/AccessRestrictionProvider.h>
26+
#include <app-common/zap-generated/cluster-objects.h>
27+
#include <app/EventLogging.h>
28+
29+
namespace chip {
30+
namespace Access {
31+
32+
class ExampleAccessRestrictionProvider : public AccessRestrictionProvider
33+
{
34+
public:
35+
ExampleAccessRestrictionProvider() : AccessRestrictionProvider() {}
36+
37+
~ExampleAccessRestrictionProvider() {}
38+
39+
protected:
40+
CHIP_ERROR DoRequestFabricRestrictionReview(const FabricIndex fabricIndex, uint64_t token, const std::vector<Entry> & arl)
41+
{
42+
// this example simply removes all restrictions and will generate AccessRestrictionEntryChanged events
43+
Access::GetAccessControl().GetAccessRestrictionProvider()->SetEntries(fabricIndex, std::vector<Entry>{});
44+
45+
chip::app::Clusters::AccessControl::Events::FabricRestrictionReviewUpdate::Type event{ .token = token,
46+
.fabricIndex = fabricIndex };
47+
EventNumber eventNumber;
48+
ReturnErrorOnFailure(chip::app::LogEvent(event, kRootEndpointId, eventNumber));
49+
50+
return CHIP_NO_ERROR;
51+
}
52+
};
53+
54+
} // namespace Access
55+
} // namespace chip

examples/platform/linux/Options.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <app/server/OnboardingCodesUtil.h>
2727

2828
#include <crypto/CHIPCryptoPAL.h>
29+
#include <json/json.h>
2930
#include <lib/core/CHIPError.h>
3031
#include <lib/support/Base64.h>
3132
#include <lib/support/BytesToHex.h>
@@ -47,6 +48,11 @@
4748

4849
using namespace chip;
4950
using namespace chip::ArgParser;
51+
using namespace chip::Platform;
52+
53+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
54+
using namespace chip::Access;
55+
#endif
5056

5157
namespace {
5258
LinuxDeviceOptions gDeviceOptions;
@@ -82,6 +88,10 @@ enum
8288
kDeviceOption_TraceFile,
8389
kDeviceOption_TraceLog,
8490
kDeviceOption_TraceDecode,
91+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
92+
kDeviceOption_CommissioningArlEntries,
93+
kDeviceOption_ArlEntries,
94+
#endif
8595
kOptionCSRResponseCSRIncorrectType,
8696
kOptionCSRResponseCSRNonceIncorrectType,
8797
kOptionCSRResponseCSRNonceTooLong,
@@ -154,6 +164,10 @@ OptionDef sDeviceOptionDefs[] = {
154164
{ "trace_log", kArgumentRequired, kDeviceOption_TraceLog },
155165
{ "trace_decode", kArgumentRequired, kDeviceOption_TraceDecode },
156166
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
167+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
168+
{ "commissioning-arl-entries", kArgumentRequired, kDeviceOption_CommissioningArlEntries },
169+
{ "arl-entries", kArgumentRequired, kDeviceOption_ArlEntries },
170+
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
157171
{ "cert_error_csr_incorrect_type", kNoArgument, kOptionCSRResponseCSRIncorrectType },
158172
{ "cert_error_csr_existing_keypair", kNoArgument, kOptionCSRResponseCSRExistingKeyPair },
159173
{ "cert_error_csr_nonce_incorrect_type", kNoArgument, kOptionCSRResponseCSRNonceIncorrectType },
@@ -280,6 +294,14 @@ const char * sDeviceOptionHelp =
280294
" --trace_decode <1/0>\n"
281295
" A value of 1 enables traces decoding, 0 disables this (default 0).\n"
282296
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
297+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
298+
" --commissioning-arl-entries <CommissioningARL JSON>\n"
299+
" Enable ACL cluster access restrictions used during commissioning with the provided JSON. Example:\n"
300+
" \"[{\\\"endpoint\\\": 1,\\\"cluster\\\": 1105,\\\"restrictions\\\": [{\\\"type\\\": 0,\\\"id\\\": 0}]}]\"\n"
301+
" --arl-entries <ARL JSON>\n"
302+
" Enable ACL cluster access restrictions applied to fabric index 1 with the provided JSON. Example:\n"
303+
" \"[{\\\"endpoint\\\": 1,\\\"cluster\\\": 1105,\\\"restrictions\\\": [{\\\"type\\\": 0,\\\"id\\\": 0}]}]\"\n"
304+
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
283305
" --cert_error_csr_incorrect_type\n"
284306
" Configure the CSRResponse to be built with an invalid CSR type.\n"
285307
" --cert_error_csr_existing_keypair\n"
@@ -320,6 +342,39 @@ const char * sDeviceOptionHelp =
320342
#endif
321343
"\n";
322344

345+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
346+
bool ParseAccessRestrictionEntriesFromJson(const char * jsonString, std::vector<AccessRestrictionProvider::Entry> & entries)
347+
{
348+
Json::Value root;
349+
Json::Reader reader;
350+
VerifyOrReturnValue(reader.parse(jsonString, root), false);
351+
352+
for (Json::Value::const_iterator eIt = root.begin(); eIt != root.end(); eIt++)
353+
{
354+
AccessRestrictionProvider::Entry entry;
355+
356+
entry.endpointNumber = static_cast<EndpointId>((*eIt)["endpoint"].asUInt());
357+
entry.clusterId = static_cast<ClusterId>((*eIt)["cluster"].asUInt());
358+
359+
Json::Value restrictions = (*eIt)["restrictions"];
360+
for (Json::Value::const_iterator rIt = restrictions.begin(); rIt != restrictions.end(); rIt++)
361+
{
362+
AccessRestrictionProvider::Restriction restriction;
363+
restriction.restrictionType = static_cast<AccessRestrictionProvider::Type>((*rIt)["type"].asUInt());
364+
if ((*rIt).isMember("id"))
365+
{
366+
restriction.id.SetValue((*rIt)["id"].asUInt());
367+
}
368+
entry.restrictions.push_back(restriction);
369+
}
370+
371+
entries.push_back(entry);
372+
}
373+
374+
return true;
375+
}
376+
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
377+
323378
bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector<uint8_t> & outVector)
324379
{
325380
size_t maxBase64Size = BASE64_ENCODED_LEN(maxSize);
@@ -529,6 +584,28 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
529584
break;
530585
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
531586

587+
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
588+
// TODO(#35189): change to use a path to JSON files instead
589+
case kDeviceOption_CommissioningArlEntries: {
590+
std::vector<AccessRestrictionProvider::Entry> entries;
591+
retval = ParseAccessRestrictionEntriesFromJson(aValue, entries);
592+
if (retval)
593+
{
594+
LinuxDeviceOptions::GetInstance().commissioningArlEntries.SetValue(std::move(entries));
595+
}
596+
}
597+
break;
598+
case kDeviceOption_ArlEntries: {
599+
std::vector<AccessRestrictionProvider::Entry> entries;
600+
retval = ParseAccessRestrictionEntriesFromJson(aValue, entries);
601+
if (retval)
602+
{
603+
LinuxDeviceOptions::GetInstance().arlEntries.SetValue(std::move(entries));
604+
}
605+
}
606+
break;
607+
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
608+
532609
case kOptionCSRResponseCSRIncorrectType:
533610
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrIncorrectType = true;
534611
break;

0 commit comments

Comments
 (0)