-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
access security #59
Comments
Implementation in PR #58 is actually fully functional. When the records are created, appropriate AS structures are initialized, using provided AS group and AS level, and those are used when record is accessed to verify whether record is write-able or not for a given client. I have verified that it works correctly by implementing corresponding python interfaces, and running instance of PvaServer in python (see https://github.com/epics-base/pvaPy/tree/access-security/documentation). Here is how things work there.
$ python Python 3.8.5 (default, Sep 4 2020, 07:30:14) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> from pvaccess import * >>> s = PvaServer() pvAccess Server v7.1.2 Active configuration (w/ defaults) EPICS_PVAS_INTF_ADDR_LIST = 0.0.0.0:5075 ... EPICS_PVAS_PROVIDER_NAMES = local >>> print(s.isAsActive()) False >>> pv = PvObject({'x' : INT}, {'x':0}) >>> s.addRecordWithAs('x', pv, 1, 'DEFAULT', None)
>>> c = Channel('x') >>> print(c.get()) structure int x 0 >>> pv = PvObject({'x' : INT}, {'x':1}) >>> c.put(pv) >>> print(c.get()) structure int x 1
$ cat /local/sveseli/EPICS/acl.conf UAG(uag) {user1,user2} HAG(hag) {host1,host2} ASG(DEFAULT) { RULE(0,READ) RULE(0,WRITE) RULE(1,READ) RULE(1,WRITE) { UAG(uag) HAG(hag) } } In python: >>> s.initAs('/local/sveseli/EPICS/acl.conf', '')
>>> c = Channel('x') >>> print(c.get()) structure int x 1 >>> pv = PvObject({'x' : INT}, {'x':2}) >>> c.put(pv) Traceback (most recent call last): File "", line 1, in pvaccess.pvaccess.PvaException: channel x PvaClientPut::put Channel put is not allowed >>> print(c.get()) structure int x 1 >>> If I modify the above file to include client's machine and username, re-run initAs() method, the record can be written again using that same client. |
I need time to think about this but let me ask:
I will be gone until tomorrow so no more from me today. |
This is true, there is no access by field in this approach, and there is no way for client to see access rules. I imagine this would cover most use cases, and I think one should certainly have the ability to enable access rule for the entire record without having to worry about individual fields. If we wanted to add access by field, we would have to add interface similar to the one you suggested, but I am not sure whether preventing read access for a field would be consistent with current practices. |
Note that for epics-base records (DBRecords) access security has provisions for access on a field by field basis.
The following are a few examples: dbCommon.dbd describes the fields that are common to every DBRecord.
special(SPC_NOMOD) in NAME states that a put can never change this field. Field ASG is used to assign a DBRecord to an access security group. aiRecord.dbd has the definitions for a aiRecord.
asl(ASL0) in VAL states that the default access security for VAL is to allow write access. The ASG field in dbCommon makes me think harder about my original suggestion at the beginning of this issue. But I still think that access security can be implemented by ChannelProviderLocal with NO changes in PVRecord. |
That's not quite true, it means that the author of the AS-config file can set different rules for ASL0 fields than for ASL1 fields. The field-level ASL0/ASL1 configuration for IOC records is per record-type, so effectively at class level, not an instance level. The older record types mostly have only their VAL field set as ASL0, but it looks like the authors of the calcout and aSub records didn't really understand the levels properly as they have weird collections of fields marked as ASL0. I don't think they are really necessary (at least to begin with) but if you do add field-level permissions for the PVRecord I would recommend that each instance be allowed to define whether a particular field should be ASL0 or ASL1, in addition to letting the server-layer know which ASG this record belongs to. I haven't tried but believe the PVA implementation will actually ignore any attempt to prevent read access to a field, it only supports preventing of write access – please don't spend any time trying to prevent reads, most clients have not been coded to expect this and will probably behave badly when presented with a PV that they can connect to but not access at all. Then there's also the new question of security for an RPC operation. Can something that accepts RPCs find out who the client is that's making the request? |
Maybe it is best, at least for now, is allow:
It does sound like allowing access on a field basis for PVRecords may be a major task. |
I merged the pull request. |
Note that I did push one change to branch access-security. I have been thinking a lot about how access security would be used with pvDatabase. I do have one question.
The reason I ask is I wonder if there might be conflicts with how access security would be used with DBRecords vs how it would be used with PVRecords. I have created exampleLink in https://github.com/mrkraimer/testDatabaseCPP. I have found that if I start an ioc with a st.cmd like
Then access security DOES apply to PVRecords!! I am now think about how to use this in exampleCPP/database. |
I don't really see why a site might want to use a different default group for PVRecords than for IOC records, I suspect that might be unusual, but if you wanted to allow for that possibility maybe instead of using a |
I just pushed changes. I have been thinking a lot about how access security could be used in an actual database application. In testSpecial is new. It has two main features: it tests pvdbcrScalar and pvdbcrScalarArrayAfter you clone and build testDatabaseCPP just do the following: In one window:
In another window:
You should see no differences It has pvdbcrTestAddRecordThis is used to test pvdbcrAddRecord This allows the ability to use either pvaClient to access the pvdbcrAddRecord or it can just access it via the PVDatabase, I want to change exampleCPP/exampleClient to do the same. |
I have just pushed changes to exampleClientCPP on branch access-security. |
While working on exampleLink I thought of more changes to pvDatabaseCPP. A change should also be made so that if a client is connected when the asGroup is changed then that client will no longer be able to make changes if the rules do not allow it. |
I just pushed more changes to branch access-security. I updated Start
Then
I hope someone gets a chance to try the latest. |
Sinisa has asked that pvDatabaseCPP support access security.
In pull request #58 he proposed changes to PRecord and ChannelProviderLocal
I have reread the epics-base access security in
https://epics.anl.gov/base/R3-16/2-docs/AppDevGuide/AccessSecurity.html#x9-3040008
But the implementation is in the epics-base code for accessing DBRecords.
This it is not usable by pvDatabaseCPP.
Here are my initial thoughts.
Access security should be implemented by ChannelProviderLocal with NO changes in PVRecord.
A configuration file would be something like the following:
Consider the following record
Some example accessdefs are
If access security is turned on then when ChannelProviderLocal is started it creates a record that provides support for access security. It would have a method:
byte would have one of the values:
0 read access
1 write access
2 no access
Just my initial thoughts.
The text was updated successfully, but these errors were encountered: