-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Make order setting mandatory for Realm config #51195
Conversation
Reserved realm and default native realms now use the new constructor to specifiy order explicitly
@tvernum This PR is still WIP. But I'd like to get a PR in early its easier for you to review and set me on the right track. Current changes are focused on making the order parameter mandatory and fixing relevant tests. Others things remaining are:
|
@elasticmachine update branch |
@elasticmachine run elasticsearch-ci/2 |
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/RealmConfig.java
Show resolved
Hide resolved
this(identifier, settings, env, threadContext, null); | ||
} | ||
|
||
public RealmConfig(RealmIdentifier identifier, Settings settings, Environment env, ThreadContext threadContext, Integer order) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better for this constructor to be protected, and update the tests to pass through real Settings
object with an order config.
I know that's going to be a pain - so please feel free to convince me if you feel otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you suggesting the caller should create a Settings
object that actually includes an order
? In this case, this constructor is no longer necessary? Am I getting this right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially actual prefer to not adding another constructor. But the number of call site changes made me change my mind. But I am happy to drop the constructor and make more call site changes if you favour this approach. Please let me know. Thanks
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/RealmConfig.java
Show resolved
Hide resolved
@tvernum
To ensure no two realms having the same order, it seems that some logic needs to be added in |
Just realised that the realms.add(fileRealm.create(new RealmConfig(
new RealmConfig.RealmIdentifier(FileRealmSettings.TYPE, "default_" + FileRealmSettings.TYPE),
settings, env, threadContext))); To add the var realmIdentifier = new RealmConfig.RealmIdentifier(FileRealmSettings.TYPE, "default_" + FileRealmSettings.TYPE);
realms.add(fileRealm.create(new RealmConfig(
realmIdentifier,
Settings.builder().put(settings)
.put(RealmSettings.realmSettingPrefix(realmIdentifier) + "order", Integer.MIN_VALUE).build(),
env, threadContext))); Note that a new |
Add tests for mandatory order setting of RealmConfig. Fix broken tests due to unique order setting requirement.
@tvernum I would like to change my view on this again ... Sorry for the back and forth. I kept the new constructor but changed the A few reasons to go with this approach:
Other changes I have pushed are:
|
Tried to identify all places in docs that are relevant to the |
@elasticmachine update branch |
Pinging @elastic/es-security (:Security/Authentication) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done a first pass.
I appreciate the effort involved, but it's one of those cases where I would've made a different choice.
But I think this works and I'll LGTM when I get to look a second time.
x-pack/docs/en/security/authentication/configuring-active-directory-realm.asciidoc
Show resolved
Hide resolved
this.enabled = getSetting(RealmSettings.ENABLED_SETTING); | ||
if (hasSetting(RealmSettings.ORDER_SETTING.apply(type())) == false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would've probably made a different choice of where to place this check because we pass RealmConfig
s around in too many places. For example, this:
- will throw an exception in
InternalRealms.getBootstrapChecks
so the stacktrace for it is funky. - will throw an exception in the
SamlMetadataCommand
which is not nice, although it might not happen in practice too often.
I would've probably removed the order
and enabled
local vars and do the checks in Realms#initRealms
. But there might be subtle problems in that case as well.
Nevertheless, this does the job, and looks OK, to me.
Nit: we use the reverse form for negative condition, i.e. false == <function>
(unless we are in some few older files that use a different convention in which case we blend with the background).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also tempted to move the logic into Reamls#initRealms
(see below) comments for details. But your examples show that by itself is not sufficient. Both of the two examples are not covered if the logic is just in Realms#initRealms
, while they do get covered if the logic is in RealmConfig
. I am now again unsure about what would be the better approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I've not made myself clear
will throw an exception in InternalRealms.getBootstrapChecks so the stacktrace for it is funky.
I mean that there is a minor inconvenience that the validation that the order
parameter is defined is performed inside a different code than the code that deals with realm construction.
this.threadContext = threadContext; | ||
this.enabled = getSetting(RealmSettings.ENABLED_SETTING); | ||
this.order = order; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to dwell on it too much, but just because we need this new constructor is a smell. In this case, the order
local var is sometimes the value from the settings
, and sometimes a different one passed by this constructor. I know this is only used in tests, but it's still not nice to have to deal with it (Integer.MAX_VALUE
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new constructor is mostly used by test code, but it is also used by production code, see Realms and ReservedRealm.
I also think adding a new constructor is not ideal due to some of the concerns you mention. It however seems to be a better choice comparing to the other choice, i.e. Add order
into the settings
parameter on caller side so that it can just keep using the existing constructor.
This approach should work fine for tests. But in production code, the settings
object is referenced in many other classes, e.g. Environment
, Realms
, etc. So when adding FileRealm (in Realms.java), if we modify the settings
object to add order
, we will need to do something like the follows:
var newSettings = Settings.Builder().put(settings).build();
... new RealmConfig(..., newSetings, ...), ...;
So the newSettings
is now passed into RealmConfig which will store a reference to it. Now we have two Settings
object across the application. They are mostly identical, only differs in the order
parameter. And this is just FileRealm, the same applies to native realm, for which we will have a third settings
. I personally think this is worse than adding a new constructor. That is why the new constructor is added so we can avoid manipulating the settings object.
With above being said, I realise it is making an assumption that the logic for mandating the order
setting resides in the RealmConfig
class. If we can move away from this assumption, like you suggested, enforce the logic in Realms.initRealms
, we can probably make the change set much smaller.
Initially I thought about adding the logic into Security
but that was too high level. So we decided to add it in RealmConfig
itself, where it is low level the logic is close to its natural owner. But maybe we need something in between. Realms
could be the right candidate especially it is where the order uniqueness is enforced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My choice would also be to only inspect the order
setting inRealms#initRealms
(where the order
value duplication is checked). That's because the order
is only really used in that place, specifying the initial order in the realm chain (which would then change as we reorder the chain during authentications), so it's not suitable as a final local variable.
This way we would also avoid having to specify the order
parameter for the "default" realms (file
and native
) which is simply ignored anyways.
Your approach works as well and I can't argue strongly against it, so this LGTM to me even though I would've approached it differently.
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecuritySettingsSource.java
Outdated
Show resolved
Hide resolved
Following discussion with Tim, I have made the following changes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you Yang!
`order` attribute to control the order in which the realms are consulted during | ||
the `url` and `order` of the LDAP server, and set `user_search.base_dn` to the | ||
container DN where the users are searched for. | ||
The `order` attribute to control the order in which the realms are consulted during | ||
authentication. See <<ref-ldap-settings>> for all of the options you can set for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This last phrase doesn't make sense, I would avoid describing again what order
does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do thanks
@@ -73,7 +72,7 @@ realms you specify are used for authentication. If you also want to use the | |||
.. Add a realm configuration to `elasticsearch.yml` in the | |||
`xpack.security.authc.realms.ldap` namespace. At a minimum, you must specify | |||
the `url` of the LDAP server, and specify at least one template with the | |||
`user_dn_templates` option. If you are configuring multiple realms, you should | |||
`user_dn_templates` option. If you are configuring multiple realms, you must | |||
also explicitly set the `order` attribute to control the order in which the | |||
realms are consulted during authentication. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove
If you are configuring multiple realms, you must ...
altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow missed this occurrence ... Will remove. Thanks
Co-Authored-By: Albert Zaharovits <[email protected]>
Co-Authored-By: Albert Zaharovits <[email protected]>
@ywangd I just remembered, we need to follow-up this PR with a another one that adds a deprecation check in https://github.com/elastic/elasticsearch/blob/7.x/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodeDeprecationChecks.java . This should inform users that realm definition sections without the |
@albertzaharovits Warning/Deprecation message for 7.x is on my to-do list. Thanks for pointing me to the right file to start with. |
Issue warnings for both missing realm order and duplicated realm orders. The changes are to help users prepare for migration to next major release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java
Outdated
Show resolved
Hide resolved
Co-Authored-By: Tim Vernum <[email protected]>
…ecurity/authc/Realms.java Co-Authored-By: Tim Vernum <[email protected]>
The changes are to help users prepare for migration to next major release (v8.0.0) regarding to the break change of realm order config. Warnings are added for when: * A realm does not have an order config * Multiple realms have the same order config The warning messages are added to both deprecation API and loggings. The main reasons for doing this are: 1) there is currently no automatic relay between the two; 2) deprecation API is under basic and we need logging for OSS.
The order parameter must be explicitly specified for each realm.
This is a breaking change and will start take effect in 8.0
Resolves: #37614