-
Notifications
You must be signed in to change notification settings - Fork 1k
oidc: Refactor lookup strategies into single functions #18169
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
base: main
Are you sure you want to change the base?
oidc: Refactor lookup strategies into single functions #18169
Conversation
Signed-off-by: Facundo Tuesca <[email protected]>
Signed-off-by: Facundo Tuesca <[email protected]>
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 like the move from using a list-in-subclass to a function-that-contains-the-complexity, as that simplifies the overall design and allows individual publishers to decide their own lookup method.
I'm also a little wary of how well-tested these publishers are. There's one functional test for provenance that creates a GitHub publisher, but everything else in theOIDC publishers stack seems heavily unit/mocked tests, so would it make sense to add some more functional tests around these interactions? The amount of mixins and abstractions make me a little cautions, being less familiar with the code behaviors.
I have a question that came up while trying to write the functional tests: I started the tests by POSTing to warehouse/warehouse/oidc/services.py Lines 343 to 346 in 79691b4
since the
Do we have a way to set it from the tests, without mocking the whole |
I believe the correct resolution for that would be to add an entry to: Lines 307 to 342 in f59df18
Similar to The |
Signed-off-by: Facundo Tuesca <[email protected]>
Nice! That worked. I've added two functional tests with a GitHub trusted publisher (while also modifying the test config to use Last question: I tried to add tests for the other providers, but OIDC is disabled for those providers in the admin flags of the test db: E webtest.app.AppError: Bad response: 422 Unprocessable Entity (not 200)
E b'{"errors":[{"code":"not-enabled","description":"gitlab trusted publishing functionality not enabled"}],"message":"Token request failed"}\n' these are the flags: warehouse/warehouse/admin/flags.py Lines 18 to 22 in 79691b4
What would be the correct way to enable them? |
I haven't fully tested this, but this should be a good start. In the context of from warehouse.admin.flags import AdminFlag, AdminFlagValue
db_sess = webtest.extra_environ['warehouse.db_session']
flag = db_sess.get(AdminFlag, AdminFlagValue.DISALLOW_GITLAB_OIDC.value)
flag.enabled = False
webtest.post(....) Or something close to it. |
This PR refactors the Trusted Publishing "lookup strategies" pattern into a single
lookup_by_claims()
method for each of the publishers.Context
A strategy is a way of, given a set of OIDC claims, query the database for a matching Trusted Publisher. Concretely, a strategy is a function that takes a set of claims and returns a
Query
object. Each publisher has a list of these strategies, ordered from specific to general. When trying to find a Trusted Publisher, the more specific strategies are tried first, and if they fail the more general ones are tried.For example, for the given set of claims for a GitHub OIDC token:
first we ran a strategy that tried to find publishers with exactly those values (in particular,
environment==my_environment
). If that strategy failed, we tried the second strategy, where we tried to find publishers withenvironment==None
(that is, allowing any environment).The "specific to general" order in this case meant going from "Publishers that only allow
my_environment
as an environment" to "Publishers that allow any environment".New implementation
This PR changes the above approach to a single function per provider called
lookup_by_claims()
which takes a set of claims and returns a Publisher.The multiple strategies are collapsed into a single query: we query for all publishers where the non-optional fields match the claims. In the example above, this means our single query looks for all publishers that match
repository
andjob_workflow_ref
, ignoring theenvironment
value.We then look at the resulting Python Publisher objects, and select the most specific one.
Rationale
The reasons for this change are:
cc @woodruffw @miketheman @di