I've discussed this at least once before, see also GERONIMO-2687.
I've been working on this idea of having all run-as and default
subjects be from login modules/configurations rather than the
current
plan of constructing subjects from confusing xml. It seems to be
working pretty well and I'm at the point where I would like to
commit
it so I'd like to find out if there are any objections to the non-
backward-compatible aspects of the changes.
The core of the idea is an interface
public interface CredentialStore {
Subject getSubject(String realm, String id) throws
LoginException;
}
that lets the servlet and ejb containers obtain a subject given an
identifier.
The CredentialStore I've implemented is currently configured with
xml
like this:
<gbean name="CredentialStore"
class="org.apache.geronimo.security.credentialstore.SimpleCredential
Stor
eImpl">
<xml-attribute name="credentialStore">
<credential-store xmlns="http://geronimo.apache.org/
xml/
ns/credentialstore-1.0">
<realm name="my-realm">
<subject>
<id>foo-run-as</id>
<credential>
<type>org.apache.geronimo.security.credentialstore.NameCallbackHandl
er</
type>
<value>foo</value>
</credential>
<credential>
<type>org.apache.geronimo.security.credentialstore.PasswordCallbackH
andl
er</type>
<value>fooPassword</value>
</credential>
</subject>
<subject>
<id>bar-run-as</id>
<credential>
<type>org.apache.geronimo.security.credentialstore.NameCallbackHandl
er</
type>
<value>bar</value>
</credential>
<credential>
<type>org.apache.geronimo.security.credentialstore.PasswordCallbackH
andl
er</type>
<value>barPassword</value>
</credential>
</subject>
</realm>
</credential-store>
</xml-attribute>
</gbean>
Note that this has cleartext passwords in it. It's a plan so after
deployment there's no textual representation of it in the car file.
This is obviously a poor feature and I'd certainly like suggestions
for improvement. One possibility is to put the configuration in a
file which can then be encrypted. However, it's difficult for me to
figure out a solution that's really secure rather than just
obfuscation.
The plan xml security configuration element now looks like this:
<security use-context-handler="false">
<default-subject>
<realm>my-realm</realm>
<id>bar-run-as</id>
</default-subject>
<role-mappings>
<role role-name="Administrator">
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="bar"/>
</realm>
</role>
<role role-name="Manager">
<subject-info>
<realm>my-realm</realm>
<id>foo-run-as</id>
</subject-info>
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="foo"/>
</realm>
</role>
</role-mappings>
</security>
This sets the default subject to bar and the run-as subject for the
Manager role to foo.
--------------------------
Comparison with current model/xml.
Currently there is nothing like the credential store configuration
and the run-as subjects are constructed from xml like this:
<security use-context-handler="false">
<default-principal realm-name="cts-properties-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="j2ee"/>
</default-principal>
<role-mappings>
<role role-name="Administrator">
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="bar"/>
</realm>
</role>
<role role-name="Manager">
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="foo" designated-run-as="true"/>
</realm>
</role>
</role-mappings>
</security>
This is somewhat limiting and I've always found it almost impossible
to understand:
Since all authorization flows from a Subject not a Principal, the
concept of default-principal is kind of ridiculous on its face.
Replacing it with a default subject allows you to configure the
default authorization with whatever detail you want.
Along with the odd practice of constructing a Subject without using
a login module, this style of configuration can be a bit confusing.
Consider this configuration example:
<security use-context-handler="false">
<role-mappings>
<role role-name="Administrator">
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="bar" designated-run-as="true"/>
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="foo"/>
</realm>
</role>
<role role-name="Manager">
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l" name="foo" designated-run-as="true"/>
</realm>
</role>
</role-mappings>
</security>
One of the effects of this configuration is that run-as="Manager"
also gets the "Administrator" role, whereas run-as="Administrator"
only gets the "Administrator" role. I find this very hard to
interpret correctly in practice. The same kind of effect can occur
in the configuration I'm proposing, but I think it will be a lot
more
obvious: you are picking a particular user in a particular login
realm and it's pretty clear that to find out what roles/permissions
that user has you have to look at all the principals involved and
trace them into the principals>>role>> permission mapping.
------------------------
Backward compatibility state:
I don't see any reasonable way to convert the previous configuration
to work exactly the same way with the new model. At the moment I've
set up the xml plan processing to delete/ignore default-principal
and
designated-run-as elements/attributes, but not try to reinterpret
them to something in the new system. So you should still be able to
deploy with an old plan, but the default identity and run as aspects
won't work as expected.
------------------------
Next steps:
-- figure out how to at least obfuscate the credentials in the
credential store configuration
-- figure out how to dynamically manage the contents of the
credential store
-- Our principal>> role mapping is extremely flexible but may often
be waaaaay more complicated than necessary. Furthermore it's just
possible that some people will want to have run-as-role mean exactly
what it seems, without any other further configuration or
flexibility. Both these concerns could be addressed by making it
possible to have a principal name == role name mapping.
One possible configuration might look like this:
<role-mappings>
<auto-map>
<realm realm-name="my-realm">
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoGroupPri
ncip
al"/>
<principal
class="org.apache.geronimo.security.realm.providers.GeronimoUserPrin
cipa
l"/>
</realm>
<run-as-realm>run-as-realm</run-as-realm>
</auto-map>
</role-mappings>
The <realm> element contains principals for which you want a
principal-name = role-name mapping.
The run-as-realm would set up a realm that requires no credentials,
just a (role) name and produce a subject with a single (role)
principal mapped to that role.
-- I don't think that including the realm in subject-info is
strictly
necessary but at this point I think it will lead to less confusion
and possible overlap, so I'm inclined to keep it. If anyone
strongly
objects it's not hard to remove.
-------------------------------
Please comment. Since this is a backward-incompatible change I
would
like to get it in quickly and definitely before 2.0 goes out the
door. I'm hoping that few enough people have ever used run-as that
it won't be a major burden on existing users.
thanks
david jencks