Geode is introducing a security features which allow Integrated Security allows you to control the authentication/authorization on of all aspects of Geode in entities within one implementation. When Integrated Security is turned on, all client/server communications, peer to peer, gateway authentication, jmx operations, gfsh commands and Pulse are all protected with this single security mechanism.
1. No changes for
...
legacy implementations of Authentication/Authorization for client-server security
The API for Authenticator and AccessControl has not changed. Your implementation implementations of those are still honored in client/server communication if you choose not to implement the new security interface. However, these two are deprecated now and will be removed in the future.
...
To turn on integrated security, your will need to start your serverservers/locator with this line locators with the security-manager
property set in your gemfire.properties
file:
Code Block | ||
---|---|---|
| ||
security-manager = com.abcexample.security.MySecurityManager |
It is a class implementing the SecurityManager interfaceThe security-manager
property identifies the class name of the SecurityManager
interface implementation. SecurityManager
is the interface you implement for both authentication and authorization. Make sure your class has a zero argument constructor so that we Geode can call to create instantiate the object. SecurityManger is the new interface you will need to implement for both authentication and authorization. See SecurityManger javadoc for details. See the SecurityManager
javadoc for details. There is an ExampleSecurityManager
in the geode-core/src/main/java/org/apache/geode/examples/security
directory that you can use as an example to write your own implementation.
3. Introduction of
...
ResourcePermission
In SecurityManager
, you will see that a GeodePermission ResourcePermission
is passed in the authorization call. GeodePermission ResourcePermission
is an object that defines the nature of the operation the Principal is trying to perform.
GeodePermission ResourcePermission
is in one of those forms:
...
All Resources are enumerated via the enum GeodePermissionResourcePermission.Resource
, which are "CLUSTER" and "DATA"currently CLUSTER
and DATA.
All Operations are enumerated via the enum GeodePermissionenum ResourcePermission.Operation
, which are " MANAGE"
, " READ"
, and " WRITE"
. Note "that MANAGE"
does not imply " WRITE"
, nor "WRITE" implies "READ" eitherand WRITE
does not imply READ
.
RegionName
and Key
are provided for those operations that are to be authorized based upon a region key access as well.For For example, you can see a GeodePermission ResourcePermission
defined as "CLUSTER:READ
", "CLUSTER:MANAGE
", "DATDADATA:READ
", "DATA:READ:regionA
", or "DATA:READ:regionA:key1
".
Note GeodePermission that a ResourcePermission
is hierarchical. If you have a principal has permission for "DATA:READ
", you it automatically have has data read permission on all regions and all keys, i.e. you have . That is, it has permission for "DATA:READ:regionA
". If you have Given permission for "DATA:READ:regionA
", you the principal automatically have has data read permission on all keys in regionA, i. e, you have That is, it has permission for "DATA:READ:regionA:key1
".
4
...
. Introduction of PostProcessor
Before a value is returned, it gets a pass through the post processor, if there is one. Specify your post processor with this line in your gemfire.properties
file:
Code Block | ||
---|---|---|
| ||
security-post-processor = com.example.security.MyPostProcessor |
where the value is the name of the class that implements the PostProcessor
interface. Make sure your class has a zero argument constructor so that Geode can instantiate the object. See the PostProcessor
javadoc for details. You can use SamplePostProcessor
as an example to write your own implementation.
Note regarding legacy implementations: We completely redo the way we call post processing; the interface is a lot simpler.
5. Operations and their corresponding ResourcePermission
Below is the list of operations with their corresponding ResourcePermission
:
Client-Server Operations
Client Operations | Required ResourcePermission |
---|---|
get function attribute | CLUSTER:READ |
create region | DATA:MANAGE |
destroy region | DATA:MANAGE |
get keyset |
5. PostProcessor
Client-Server
Client Operations | Required GeodePermission | |||
---|---|---|---|---|
region.containsKeyOnServer(key) | DATA:READ:regionName | |||
query | DATA:READ:regionName:key | |||
region. | destroy(key)getAll | DATA: | WRITEREAD:regionName | :key|
region.invalidate(keygetEntry | DATA:READ:regionName | |||
getAll (list of keys) | DATA:WRITEREAD:regionName:key | |||
region. | putcontainsKeyOnServer(key | , value) | DATA: | WRITEREAD:regionName:key |
region.get(key) | DATA:READ:regionName:key | |||
region.replace | ||||
region.putIfAbsent | ||||
createRegion | DATA:MANAGE | |||
destroyRegion | DATA:MANAGE | |||
executeFunction | DATA:WRITE | |||
registerInterest | DATA:READ:regionName:key if key is specified, otherwise DATA:READ:regionName | |||
unregister interest | DATA:READ:regionName:key if key is specified, otherwise DATA:READ:regionName | |||
execute function | executeRegionFunctionDATA:WRITE | |||
clear region | .getAllDATA: | READWRITE:regionName | region.getEntry||
putAll | DATA: | READWRITE:regionName | ||
region.clear | DATA:WRITE:regionName | |||
region. | registerInterestremoveAll | DATA: | READWRITE:regionName | :keyregion.registerInterestRegex|
destroy key | DATA: | READWRITE:regionName | :key | |
invalidate key | region.registerInterestListDATA: | READWRITE:regionName:key | ||
region. | removeAlldestroy(key) | DATA:WRITE:regionName:key | ||
region. | unRegisterInterestinvalidate(key) | DATA: | READWRITE:regionName:key | |
region. | unRegisterInterestRegexput(key, value) | DATA: | READWRITE:regionName:key | |
region. | unRegisterInterestListreplace | DATA: | READWRITE:regionName | |
query | DATA:READ:regionName | |||
Pulse
Pulse access is divided into two main categories, namely access to the Data Browser page and everything else.
The Data Browser page requires the permissions CLUSTER:READ and DATA:READ. Access to all other pages requires only CLUSTER:READ permission.
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.
Entries with a green background are gfsh commands; the others are JMX operations.
:key |
GFSH Commands
Commands | Required ResourcePermission | ||||
---|---|---|---|---|---|
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 | CLUSTERDATA: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 | ||||
show log | 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 | ||||
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: | REGIONNAMEregionName | |||
create region --name=region12 | DATA:MANAGE | ||||
define index --name=myIndex1 --expression=exp1 --region=/exampleRegion | DATA:MANAGE: | REGIONNAMEregionName | |||
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:regionName if regionName is specified, otherwise DATA:MANAGE | |||
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=region1DATA:MANAGE | remove- | -region=region1 | DATA:MANAGE | , if key is specified......|
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 | ||||
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:key | ||||
locateEntry | DATA:READ:regionName:key | ||||
query --query='SELECT * FROM /region1' | DATA:READ:REGIONNAME | ||||
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:key | ||||
remove --region=region1 | DATA:WRITE:regionName, if key is specified, then DATA:WRITE:regionName:key | ||||
alter jdbc-connection | CLUSTER:MANAGE | ||||
alter jdbc-mapping | CLUSTER:MANAGE | ||||
create jdbc-connection | CLUSTER:MANAGE | ||||
create jdbc-mapping | CLUSTER:MANAGE | ||||
describe jdbc-connection | CLUSTER:MANAGE | ||||
describe jdbc-mapping | CLUSTER:MANAGE | ||||
destroy jdbc-connection | CLUSTER:MANAGE | ||||
destroy jdbc-mapping | CLUSTER:MANAGE | ||||
list jdbc-connections | CLUSTER:MANAGE | ||||
list jdbc-mappings | CLUSTER:MANAGE | ||||
create jndi-binding | CLUSTER:MANAGE | ||||
describe jndi-binding | CLUSTER:READ | ||||
destroy jndi-binding | CLUSTER:MANAGE | ||||
list jndi-binding | CLUSTER:READ |
Pulse
Pulse access is divided into two main categories: access to the Data Browser page and everything else.
The Data Browser page requires the permissions CLUSTER:READ and DATA:READ. Access to all other pages requires only CLUSTER:READ permission.
JMX Operations
Bean Operations | Permission |
---|---|
DistributedSystemMXBean.shutdownAllMembers | CLUSTER:MANAGE |
ManagerMXBean.start | CLUSTER:MANAGE |
ManagerMXBean.stop | CLUSTER:MANAGE |
MemberMXBean.createManager()) | CLUSTER:MANAGE |
MemberMXBean.shutDownMember | CLUSTER:MANAGE |
Mbeans get attributes | CLUSTER:READ |
MemberMXBean.showLog | CLUSTER:READ |
DistributedSystemMXBean.changeAlertLevel | CLUSTER:WRITE |
ManagerMXBean.setPulseURL | CLUSTER:WRITE |
ManagerMXBean.setStatusMessage | CLUSTER:WRITE |
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:key |
DATA:READ:regionName:key | |
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:key
Content by Label | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
...