Geode is introducing additional security features which allow finer grained control for JMX operations as well as GFSH commands. This page describes those changes and new functionality which has been introduced.
1. No changes for existing implementations of Authenticator and AccessControl for client-server security
The API for authentication and authorization has not changed. However, in order to authorize and secure JMX and GFSH operations, existing implementations will need to be modified.
2. Introduction of Resource and OperationCode
The notion of a permission in the form of a noun (Resource) and verb (OperationCode) is being introduced. This will typically be represented as a colon-separated tuple in the form of RESOURCE:OPERATION_CODE. In some cases, permissions are also applicable to regions; in such cases the permission would be in the form RESOURCE:OPERATION_CODE:REGION. Currently the following have been defined:
Resource
- CLUSTER
- DATA
Operation
- MANAGE
- READ
- WRITE
- CLOSE_CQ
- CONTAINS_KEY
- DESTROY
- EXECUTE_CQ
- EXECUTE_FUNCTION
GET
- GET_DURABLE_CQS
- INVALIDATE
- KEY_SET
PUT
PUTALL
- QUERY
REGION_CLEAR
REGION_CREATE
REGION_DESTROY
REGISTER_INTEREST
REMOVEALL
- STOP_CQ
UNREGISTER_INTEREST
Operations in RED refer to existing client-server operations.
The Reference section, at the end of this page, details all permissions for Client-Server as well as JMX and CLI operations.
3. Expanded functionality for OperationContext
All Resources are enumerated via the enum OperationContext.Resource.
All OperationCodes are enumerated via the enum OperationContext.OperationCode.
All of the existing OperationContext.is*
methods have been deprecated in favor of testing against the relevant enums.
The resource and operation code, for a given context, can be retrieved using OperationContext.getResource
and OperationContext.getOperationCode
respectively.
Existing code, implementing AccessControl, would have needed to check the type of the OperationContext as passed into the authorizeOperation
method. This is still possible, however it will now be easier to achieve the same functionality by simply checking the Resource and OperationCode of the context. For example, existing code might have looked like this:
@Override public boolean authorizeOperation(String regionName, OperationContext context) { if (context instanceof PutOperationContext) { // cast to PutOperationContext } else if (context instanceof QueryOperationContext) { // cast to QueryOperationContext } else { // Must be JMX or CLI } return false; }
Can now be changed to:
@Override public boolean authorizeOperation(String regionName, OperationContext context) { switch (context.getOperationCode()) { case PUT: // cast to PutOperationContext break; case QUERY: // cast to QueryOperationContext break; case READ: case WRITE: case MANAGE: // Must be JMX or CLI - no need to cast; just use the 'context' as is break; } return false; }
Note that any JMX or CLI contexts are not associated with a specific sub-type of OperationContext and can be handled without having to cast the context parameter.
All client-server operations are associated with a Resource of DATA.
Reference
Client-Server
Client-server permissions are associated with their respective OperationContexts as follows. Permissions appear as Resource:OperationCode
tuples.
OperationContext | Permission |
---|---|
CloseCQOperationContext | DATA:CLOSE_CQ |
ContainsKeyOperationContext | DATA:CONTAINS_KEY |
DestroyOperationContext | DATA:DESTROY |
ExecuteCQOperationContext | DATA:EXECUTE_CQ |
ExecuteFunctionOperationContext | DATA:EXECUTE_FUNCTION |
GetDurableCQsOperationContext | DATA:GET_DURABLE_CQS |
GetOperationContext | DATA:GET |
InvalidateOperationContext | DATA:INVALIDATE |
KeySetOperationContext | DATA:KEY_SET |
PutAllOperationContext | DATA:PUTALL |
PutOperationContext | DATA:PUT |
QueryOperationContext | DATA:QUERY |
RegionClearOperationContext | DATA:REGION_CLEAR |
RegionCreateOperationContext | DATA:REGION_CREATE |
RegionDestroyOperationContext | DATA:REGION_DESTROY |
RegisterInterestOperationContext | DATA:REGISTER_INTEREST |
RemoveAllOperationContext | DATA:REMOVEALL |
StopCQOperationContext | DATA:STOP_CQ |
UnregisterInterestOperationContext | DATA:UNREGISTER_INTEREST |
GFSH and JMX
Following are lists for gfsh commands, (highlighted in green), and JMX operations with their corresponding permissions. Permissions appear as Resource:OperationCode
tuples.
Cluster MANAGEment Operations | Permission |
---|---|
alter runtime | CLUSTER:MANAGE |
gc | CLUSTER:MANAGE |
shutdown | CLUSTER:MANAGE |
startManager | CLUSTER:MANAGE |
stop locator --name=locator1 | CLUSTER:MANAGE |
stop server --name=server1 | CLUSTER:MANAGE |
DistributedSystemMXBean.shutdownAllMembers | CLUSTER:MANAGE |
ManagerMXBean.start | CLUSTER:MANAGE |
ManagerMXBean.stop | CLUSTER:MANAGE |
MemberMXBean.createManager()) | CLUSTER:MANAGE |
MemberMXBean.shutDownMember | CLUSTER:MANAGE |
Cluster READ Operations | Permission |
---|---|
countDurableCqEvents | CLUSTER:READ |
describe client --clientID=172.16.196.144 | CLUSTER:READ |
describe config --member=Member1 | CLUSTER:READ |
describe disk-store --name=foo --member=baz | CLUSTER:READ |
describe member --name=server1 | CLUSTER:READ |
describe offline-disk-store --name=foo --disk-dirs=bar | CLUSTER:READ |
describe region --name=value | CLUSTER:READ |
export cluster-configuration --zip-file-name=mySharedConfig.zip | CLUSTER:READ |
export config --member=member1 | CLUSTER:READ |
export logs --dir=data/logs | CLUSTER:READ |
export stack-traces --file=stack.txt | CLUSTER:READ |
exportLogs | CLUSTER:READ |
exportStackTrace | CLUSTER:READ |
list async-event-queues | CLUSTER:READ |
list clients | CLUSTER:READ |
list deployed | CLUSTER:READ |
list disk-stores | CLUSTER:READ |
list durable-cqs --durable-client-id=client1 | CLUSTER:READ |
list functions | CLUSTER:READ |
list gateways | CLUSTER:READ |
list indexes | CLUSTER:READ |
list members | CLUSTER:READ |
list regions | CLUSTER:READ |
netstat --member=server1 | CLUSTER:READ |
show dead-locks --file=deadlocks.txt | CLUSTER:READ |
show log --member=locator1 --lines=5 | CLUSTER:READ |
show metrics | CLUSTER:READ |
show missing-disk-stores | CLUSTER:READ |
show subscription-queue-size --durable-client-id=client1 | CLUSTER:READ |
showLog | CLUSTER:READ |
status cluster-config-service | CLUSTER:READ |
status gateway-receiver | CLUSTER:READ |
status gateway-sender | CLUSTER:READ |
Mbeans get attributes | CLUSTER:READ |
MemberMXBean.showLog | CLUSTER:READ |
Cluster WRITE Operations | Permission |
---|---|
change loglevel --loglevel=severe --member=server1 | CLUSTER:WRITE |
DistributedSystemMXBean.changeAlertLevel | CLUSTER:WRITE |
ManagerMXBean.setPulseURL | CLUSTER:WRITE |
ManagerMXBean.setStatusMessage | CLUSTER:WRITE |
Data MANAGE Operations | Permission |
---|---|
alter disk-store --name=foo --region=xyz --disk-dirs=bar | DATA:MANAGE |
alter region --name=region1 --eviction-max=5000 | DATA:MANAGE:REGIONNAME |
clear defined indexes | DATA:MANAGE |
close durable-client --durable-client-id=client1 | DATA:MANAGE |
close durable-cq --durable-client-id=client1 --durable-cq-name=cq1 | DATA:MANAGE |
compact disk-store --name=foo | DATA:MANAGE |
compact offline-disk-store --name=foo --disk-dirs=bar | DATA:MANAGE |
configure pdx --read-serialized=true | DATA:MANAGE |
create async-event-queue --id=myAEQ --listener=myApp.myListener | DATA:MANAGE |
create defined indexes | DATA:MANAGE |
create disk-store --name=foo --dir=bar | DATA:MANAGE |
create gateway-receiver | DATA:MANAGE |
create gateway-sender --id=sender1 --remote-distributed-system-id=2 | DATA:MANAGE |
create index --name=myKeyIndex --expression=region1.Id --region=region1 --type=key | DATA:MANAGE:REGIONNAME |
create region --name=region12 | DATA:MANAGE |
define index --name=myIndex1 --expression=exp1 --region=/exampleRegion | DATA:MANAGE:REGIONNAME |
deploy --jar=group1_functions.jar --group=Group1 | DATA:MANAGE |
destroy disk-store --name=foo | DATA:MANAGE |
destroy function --id=InterestCalculations | DATA:MANAGE |
destroy index --member=server2 | DATA:MANAGE:REGIONNAME |
destroy region --name=value | DATA:MANAGE |
import cluster-configuration --zip-file-name=value | DATA:MANAGE |
load-balance gateway-sender --id=sender1 | DATA:MANAGE |
pause gateway-sender --id=sender1 | DATA:MANAGE |
pdx rename --old=com.gemstone --new=com.pivotal --disk-store=ds1 --disk-dirs=/diskDir1 | DATA:MANAGE |
rebalance --include-region=region1 | DATA:MANAGE |
remove --region=region1 | DATA:MANAGE |
resume gateway-sender --id=sender1 | DATA:MANAGE |
revoke missing-disk-store --id=foo | DATA:MANAGE |
start gateway-receiver | DATA:MANAGE |
start gateway-sender --id=sender1 | DATA:MANAGE |
stop gateway-receiver | DATA:MANAGE |
stop gateway-sender --id=sender1 | DATA:MANAGE |
undeploy --group=Group1 | DATA:MANAGE |
CacheServerMXBean.closeAllContinuousQuery | DATA:MANAGE |
CacheServerMXBean.closeContinuousQuery | DATA:MANAGE |
CacheServerMXBean.removeIndex("foo")) | DATA:MANAGE |
CacheServerMXBean.stopContinuousQuery("bar")) | DATA:MANAGE |
DiskStoreMXBean.flush()) | DATA:MANAGE |
DiskStoreMXBean.forceCompaction()) | DATA:MANAGE |
DiskStoreMXBean.forceRoll()) | DATA:MANAGE |
DiskStoreMXBean.setDiskUsageCriticalPercentage(0 | DATA:MANAGE |
DiskStoreMXBean.setDiskUsageWarningPercentage(0 | DATA:MANAGE |
DistributedSystemMXBean.revokeMissingDiskStores | DATA:MANAGE |
DistributedSystemMXBean.setQueryCollectionsDepth | DATA:MANAGE |
DistributedSystemMXBean.setQueryResultSetLimit | DATA:MANAGE |
GatewayReceiverMXBean.pause()) | DATA:MANAGE |
GatewayReceiverMXBean.rebalance()) | DATA:MANAGE |
GatewayReceiverMXBean.resume()) | DATA:MANAGE |
GatewayReceiverMXBean.start | DATA:MANAGE |
GatewayReceiverMXBean.stop | DATA:MANAGE |
GatewaySenderMXBean.pause | DATA:MANAGE |
GatewaySenderMXBean.rebalance | DATA:MANAGE |
GatewaySenderMXBean.resume | DATA:MANAGE |
GatewaySenderMXBean.start | DATA:MANAGE |
GatewaySenderMXBean.stop | DATA:MANAGE |
LockServiceMBean.becomeLockGrantor()) | DATA:MANAGE |
MemberMXBean.compactAllDiskStores | DATA:MANAGE |
Data READ Operations | Permission |
---|---|
backup disk-store --dir=foo | DATA:READ |
export data --region=region1 --file=foo.txt --member=value | DATA:READ:REGIONNAME |
get --key=key1 --region=region1 | DATA:READ:REGIONNAME |
locateEntry | DATA:READ:REGIONNAME |
query --query='SELECT * FROM /region1' | DATA:READ:REGIONNAME |
CacheServerMXBean.executeContinuousQuery("bar")) | DATA:READ |
DistributedSystemMXBean.backupAllMembers | DATA:READ |
DistributedSystemMXBean.queryData | DATA:READ |
DistributedSystemMXBean.queryDataForCompressedResult | DATA:READ |
Data WRITE Operations | Permission |
---|---|
execute function --id=InterestCalculations --group=Group1 | DATA:WRITE |
import data --region=region1 --file=foo.txt --member=value | DATA:WRITE:REGIONNAME |
put --key=key1 --value=value1 --region=region1 | DATA:WRITE:REGIONNAME |