db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rick Hillegas (Commented) (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DERBY-866) Derby User Management Enhancements
Date Tue, 06 Mar 2012 15:35:58 GMT

    [ https://issues.apache.org/jira/browse/DERBY-866?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13223333#comment-13223333
] 

Rick Hillegas commented on DERBY-866:
-------------------------------------

At this point, I am declaring victory on the coding/unit-testing of NATIVE authentication.
I believe that I have implemented and verified all of the functionality in the spec. I have
reached the end of my ability to test this feature productively. My blinders, as the author
of this feature, prevent me from discovering additional defects. The tests I have written
lately do disclose defects in other parts of Derby outside the scope of this feature--but
not new defects in NATIVE authentication itself.

However, I'm sure there are plenty of remaining defects, perhaps even some real howlers. At
this point, buddy-testers may be able to find some of the defects hidden behind my blinders.

To help buddy-testers guess where the weaknesses lie, I would like to describe the current
implementation and its touchpoints with other parts of Derby.

--------------------------------------------------
-- NATIVE Authentication Service
--------------------------------------------------

The core of the implementation is the NATIVE authentication service itself, NativeAuthenticationServiceImpl.
This implementation is parallel to the other authentication services, and like them, it extends
AuthenticationServiceBase:

1) BasicAuthenticationServiceImpl - This class implements BASIC authentication. I used it
as the template for NativeAuthenticationServiceImpl because NATIVE and BASIC authentication
share a key trickiness: the storing of credentials inside the database being connected to.

2) JNDIAuthenticationServiceImpl - This class handles LDAP authentication.

3) SpecificAuthenticationServiceImpl - This class handles user-written authenticators.

4) NoneAuthenticationServiceImpl - This is the default, NOP authentication service used when
the application does not require any authentication at all.

At engine and database startup, all of these implementations of the authentication module
are asked whether they match the setting of the Derby authentication properties. I had to
modify SpecificAuthenticationServiceImpl because it is the catch-all implementation: by default
it matches any setting of derby.authentication.provider which has not been excluded explicitly.
There are quite a few Derby authentication properties:

  derby.authentication.builtin.algorithm
  derby.authentication.ldap.searchAuthDN
  derby.authentication.ldap.searchAuthPW
  derby.authentication.ldap.searchBase
  derby.authentication.ldap.searchFilter
  derby.authentication.provider
  derby.authentication.server
  derby.connection.requireAuthentication

--- Bootstrapping

The first bit of trickiness in NativeAuthenticationServiceImpl is the logic which determines
whether this implementation matches the setting of the Derby authentication properties. This
is tricky because unlike the other authentication services, NATIVE authentication is supposed
to be easy for the user to configure. It only requires that you set one property, viz. derby.authentication.provider.
The other authentication services require that you redundantly set derby.connection.requireAuthentication.

Bootstrapping NATIVE authentication follows the normal Derby model, which divides bootstrapping
into two phases: canSupport() and boot(). Validation of property settings can't be performed
by canSupport() because that method does not let you raise an invalidation exception. Note
that this behavior gives rise to the quirky result that if you garble the setting of derby.authentication.provider,
you will end up booting the catch-all SpecificAuthenticationServiceImpl, which will promptly
fall over because the garbled derby.authentication.provider does not resolve to a valid class
name.

However, deferring the validation of derby.authentication.provider to NativeAuthenticationServiceImpl.boot()
is fine. That is because the NATIVE authentication service needs to know whether it is being
booted system-wide or inside a specific database. The value NATIVE::LOCAL is meaningless for
system-wide authentication but it is the only legal value which can be stored in a database.
That last point is true because we don't want to hard-code the name of the system-wide credentials
db inside any specific database; we want the database to be portable and we want to give the
system administrator the option of moving the credentials db if there is a problem.

--- Creating the credentials DB

The next bit of trickiness involves coupling connection management with NATIVE authentication.
Special logic in EmbedConnection checks to see whether the database being created is the credentials
database. If so, authentication isn't performed: there is no authentication authority yet
and the presented credentials are simply accepted as is and will be used to create the DBO
account. It might make more sense if this logic were inside NativeAuthenticationServiceImpl.
However, the knowledge that the database is being created is not passed across the authentication
call, so NativeAuthenticationServiceImpl can't perform this check.

--- Steady-state

The rest of the logic in NativeAuthenticationServiceImpl happens under authenticateUser()
and processes the main execution path: authenticating users for system-wide or database-specific
tasks. At this point the NATIVE authentication service is booted and we know that we are not
authenticating the creation of the credentials db itself.

The authenticateUser() method figures out whether credentials should be looked up in the current
database or in another database.

Looking up the credentials in another database gives rise to the next bit of trickiness. This
logic has already been corrected to account for a deadlock in the Java 5 VM. We were doing
something which fell outside the main execution path understood by  the VM's JDBC layer, viz.,
we were trying to open a nested JDBC connection in the middle of establishing an outer JDBC
connection. After the corrective logic, we are now merely trying to establish a nested Derby
connection while trying to establish an outer Derby connection. Needless to say, this still
falls outside the main execution path understood by Derby and there may be bugs lurking here.

Other trickiness may lurk inside the logic which looks up credentials in the current database.
To find the real credentials, we must access the Store before the connection has been completely
established. Fortunately, BUILTIN authentication has been doing this for years so many bugs
in this area may have been flushed out already. We also access the DataDictionary before the
connection has been completely established. This unusual code path is not exercised by BUILTIN
authentication and so it may be hiding some bugs.


--------------------------------------------------
-- Properties Management
--------------------------------------------------

NATIVE authentication attempts to be simple to configure and hard to turn off. All you have
to do is turn one knob (the derby.authentication.provider property). When you turn this knob
to NATIVE authentication, you also turn on SQL authorization. Once NATIVE authentication has
been set in the database itself, it can't be disabled. 

The interaction of Derby properties is already complicated and is influenced by the following
considerations:

o Whether the property is set on the VM command line, in
derby.properties, or in the database.

o Whether the special derby.database.propertiesOnly property is set.

o Whether other, related properties have been set correctly.

I confess to being confused repeatedly by the way that Derby properties interact. And now
I have complicated that interaction by introducing the peculiar, trumping behaviors of NATIVE
authentication. The goal was to simplify how users protect their data, but I can't promise
that edge cases haven't crept in or been made worse. A crucial piece of trumping happens in
PropertyUtil.getPropertyFromSet(). There could be more bugs in this area as well.


--------------------------------------------------
-- Data Dictionary
--------------------------------------------------

The Data Dictionary assists NATIVE authentication. Here are the major touchpoints:

1) A new SYSUSERS catalog has been added. Unlike other catalogs, ordinary users can't view
this catalog (when authentication is on) and even the DBO can't view the PASSWORD column.
These behaviors are unprecedented so they may be particularly buggy.

2) I added 4 new procedures for managing passwords: syscs_util.syscs_create_user, syscs_util.syscs_drop_user,
syscs_util.syscs_reset_password, and syscs_util.syscs_modify_password. The first 3 are modelled
on other, existing DBO-only procedures. The last procedure is modelled on existing procedures
which anyone can run.

3) I moved the password-hashing logic into a PasswordHasher class in the Data Dictionary.

                
> Derby User Management Enhancements
> ----------------------------------
>
>                 Key: DERBY-866
>                 URL: https://issues.apache.org/jira/browse/DERBY-866
>             Project: Derby
>          Issue Type: Improvement
>          Components: Services
>    Affects Versions: 10.2.1.6
>            Reporter: Francois Orsini
>            Assignee: Rick Hillegas
>         Attachments: Derby_User_Enhancement.html, Derby_User_Enhancement_v1.1.html, DummyAuthenticator.java,
UserManagement.html, UserManagement.html, UserManagement.html, UserManagement.html, UserManagement.html,
UserManagement.html, derby-866-01-aa-sysusers.diff, derby-866-01-ab-sysusers.diff, derby-866-02-ag-createDropUser.diff,
derby-866-03-aa-resetModifyPassword.diff, derby-866-03-ab-resetModifyPassword.diff, derby-866-04-aa-fixRolesTest.diff,
derby-866-05-aa-grantRevoke.diff, derby-866-06-aa-upgradeFrom10.1.diff, derby-866-07-aa-removeSQLPassword.diff,
derby-866-08-aa-passwordHasher.diff, derby-866-08-ab-passwordHasher.diff, derby-866-08-ad-passwordHasher.diff,
derby-866-09-ad-nativeAuthenticationService.diff, derby-866-09-ae-nativeAuthenticationServiceWithTests.diff,
derby-866-10-ac-propChanging.diff, derby-866-11-aa-upgradeTest.diff, derby-866-12-ac-passwordExpiration.diff,
derby-866-13-ab-systemWideOperationTests.diff, derby-866-14-ac-badNativeSpec.diff, derby-866-15-ae-dbInJarFileOrOnClasspath.diff,
derby-866-16-aa-credDBViaSubprotocol.diff, derby-866-17-aa-grantRevokeNative.diff, derby-866-18-aa-encryptedCredentialsDB.diff,
derby-866-19-aa-replicationTest.diff, derby-866-20-aa-npeAndUserProbing.diff, derby-866-20-ab-npeAndUserProbing.diff,
derby-866-21-aa-emptyCredentials.diff, derby-866-21-ab-emptyCredentials.diff, dummyCredentials.properties,
releaseNote.html
>
>
> Proposal to enhance Derby's Built-In DDL User Management. (See proposal spec attached
to the JIRA).
> Abstract:
> This feature aims at improving the way BUILT-IN users are managed in Derby by providing
a more intuitive and familiar DDL interface. Currently (in 10.1.2.1), Built-In users can be
defined at the system and/or database level. Users created at the system level can be defined
via JVM or/and Derby system properties in the derby.properties file. Built-in users created
at the database level are defined via a call to a Derby system procedure (SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY)
which sets a database property.
> Defining a user at the system level is very convenient and practical during the development
phase (EOD) of an application - However, the user's password is not encrypted and consequently
appears in clear in the derby.properties file. Hence, for an application going into production,
whether it is embedded or not, it is preferable to create users at the database level where
the password is encrypted.
> There is no real ANSI SQL standard for managing users in SQL but by providing a more
intuitive and known interface, it will ease Built-In User management at the database level
as well as Derby's adoption.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

Mime
View raw message