Problem/Motivation
As done in #2856713: Authentication plugins and HTTP authentication, there are now authentication plugins.
In the configuration there is now an UUID used to store sensible data locally in a state:
entity_share_client.remote.*:
type: config_entity
label: 'Remote config'
mapping:
...
auth:
type: mapping
mapping:
pid:
label: 'Plugin ID'
type: string
uuid:
label: 'UUID'
type: string
And there is the entity_share_client_update_8201 that handles the update.
I was thinking about it and I think it will provoke problems with multiple environments.
Because the UUID generated will be different per environment, when using a config import, the UUID will then differ from the one used to create the state. So the login/password saved in the state will no more be usable (at least without custom code or custom config overrides using settings.php or something else to force UUID).
Proposed resolution
- Use the remote config entity's UUID, so that it won't change per environment.
- Use a dedicated key_value collection and no more state for local storage
Also this will ease managing config overrides in settings.php, config_split, or anything else and will ease scripting for example local storage key value creation.
Remaining tasks
- Discuss about this issue
- See if there won't be any other problem
- Create a patch
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | interdiff-3172390-19-20.txt | 5.29 KB | fathershawn |
| #20 | update_concern_regar-3172390-20.patch | 22.33 KB | fathershawn |
| #19 | interdiff-3172390-18-19.txt | 644 bytes | grimreaper |
| #19 | entity_share-update_concern-3172390-19.patch | 23.33 KB | grimreaper |
| #18 | interdiff_14_18.txt | 4.62 KB | fathershawn |
Comments
Comment #2
fathershawnPerhaps I'm missing a link in the logic chain, but I don't think this is correct. Here's how I see it.
A Remote is created and the authorization plugin is chosen. The configuration for this plugin, including its UUID is included as a child of the remote's config:
When
\Drupal\entity_share_client\Entity\Remote::getAuthPluginis run the plugin configuration is loaded:The plugin id is extracted from this array so that the remaining keys form a configuration array, and the plugin is loaded with this config. Once the plugin has been created the UUID is persistent.
What varies by environment is the value stored in State. But in my view it should vary, especially for Oauth. Each environment should be using it's own consumer on the hub. I'm fairly certain that a variety of issues that I saw in testing were the result of environment B getting a new token from the same consumer used by environment A, causing the requests from A to fail because they were sharing a consumer and the token stored by A had been invalidated by the new token creation for B.
Comment #3
grimreaperThanks @FatherShawn for the reply.
Yes, when creating a remote configuration and deploying it, the UUID in:
will not change, but my concern is about the update entity_share_client_update_8201().
As it will change the remote configurations from the previous structure to the new one, it will create new uuids the time to run the update, then when using configuration management, when doing "drush config:import" it will the UUID from the versionned config entity.
So if on the development environment (A), I have:
on this environment, there will be a state with 33f847c6-4024-4d7b-b5d8-df95a398c4dc, that will store the data: OK
When on another environment (B), executing entity_share_client_update_8201(), will give:
And so there will be a state "something-else" that will store the data, then config import will transform it back to:
But there will not be a state "33f847c6-4024-4d7b-b5d8-df95a398c4dc" created on environment B: KO
I agree that you can then go on environment B and save the remote form so the state "33f847c6-4024-4d7b-b5d8-df95a398c4dc" will be created, but:
1. the update is here to avoid manual steps
2. "something-else" will be "orphan" and will stay indefinitely in the database.
Is my concern better expressed like this?
(also I am definitely for a dedicated key_value collection and no more a state otherwise it is impossible to clean things when uninstalling the module or to clean it for another reason)
Comment #4
fathershawnThanks for clarifying. Now I understand. I do like the idea of a dedicated key-value collection. That's a great idea that accomplishes the intent of my use of State but with all the benefits that you name.
I'll have a close look at the update hook to see if I have a suggestion for this case.
Comment #5
fathershawnSee what you think of this approach?
Comment #6
grimreaperThanks @FatherShawn for the reply.
Hum, I think in comment 5 you are trying to handle something else. But it gave me the solution for the update.
Please see attached patch.
Also I tested to delete a remote config entity and the state is not deleted.
So if the update is ok for you next step will be (I will do it if I have the time) to switch from state to key value collection and implement an hook to clean it when the config entity is deleted.
Comment #7
fathershawnAs I read your approach, it is to always use the same uuid in the update, so if there is a config import following, and that config is from an update that took place in a prior environment, it overwrites the uuid with the same value. Result: only one value is stored.
My code was aiming to solve the problem a different way, but your way is simpler. I like it.
Will the key/value change be in this issue or another?
Comment #8
grimreaperThanks for your feedback :)
Hum, update aside, with the current codebase in the dev version, when you import configuration the state is not updated.
So maybe it is how your sentence "and that config is from an update" is done, I am not 100% sure that we are talking about the same thing. But as you are ok with my proposition I guess it is the same thing finally :D
Yes it will be in this issue that the key_value change will happen. :)
Comment #9
grimreaperComment #10
grimreaperHello,
And here is the patch. Testing manually while triggerring Drupal CI.
Comment #12
grimreaperI forgot the hook to delete the key_value when the config is deleted.
And when switching authentication method, a new UUID is generated so the previous key_value is not deleted.
Comment #13
grimreaperComment #14
grimreaperI have just realized that the "password" form element on the Basic Auth plugin was not of type password.
Comment #15
grimreaperHi @FatherShawn,
Waiting for your review before merging and making the first beta release :)
Comment #16
fathershawnI can see why you want to use a common value for the auth plugin uuid in RemoteForm when a plugin has been previously stored. I had the get past the idea that in one sense it was no longer "universally unique." But we are really using it as a storage key.
However, I think this is better handled by `ClientAuthorizationPluginManager::getAvailablePlugins`.
In ClientAuthorization we are inconsistent with the value of the key used for storing into KeyValue, and I see some other inconsistencies about when values are set and deleted. For example, in some places `-oauth` is appended to the end of the uuid to make a key and in some not. Some of that may trace back to my original draft, or the blending of our code. I'm auditing all the places that we store or retrieve and refactoring it to be consistent.
I have a proposed patch in progress but I'm being pulled back into client work that's needed first and then I'll circle back
Comment #17
grimreaperThanks @FatherShawn for the feedback!
Waiting for your patch.
And no problem about priority to client work. We are used to that too ;)
Comment #18
fathershawnWith fresh eyes the "inconsistency" that I thought I saw was in my memory and not the code. I added some comments instead. But I did move the common uuid process as discussed above. Here's a patch against the latest 3.x with an interdiff as well.
Comment #19
grimreaperHello @FatherShawn,
I really like your approach of the new argument in getAvailablePlugins().
The point on Oauth plugin made me make a little adjustment in entity_share_client_remote_delete().
A last review and I think we are done with this issue.
Comment #20
fathershawnAlmost, or we could be done depending on what you think. Good catch on Oauth having secondary storage. That prompts me to say that perhaps we should establish a convention of using the plugin id and make this more general. I've refactored one more time with that in mind.
Comment #21
grimreaperNice idea! Thanks!
Doing a last manual testing and then merge and then release!!!
Comment #23
grimreaperAnd this is merged now!
Thanks for your help!