Today’s anonymous submitter spent a few weeks feeling pretty good about themselves. You see, they’d inherited a gigantic and complex pile of code, an application spread out across 15 backend servers, theoretically organized into “modules” and “microservices” but in reality was a big ball of mud. And after a long and arduous process, they’d dug through that ball of mud and managed to delete 190 files, totaling 30,000 lines of code. That was fully 2/3rds of the total codebase, gone- and yet the tests continued to pass, the application continued to run, and everyone was just much happier with it.
Two weeks later, a new ticket comes in: users are getting a 403 error when trying to access the “User Update” screen. Our submitter has seen a lot of these tickets, and it almost always means that the user’s permissions are misconfigured. It’s an easy fix, and not a code problem.
Just to be on the safe side, though, they pull up the screen with their account- guaranteed to have the right permissions- and get a 403.
As you can imagine, the temptation to sneak a few fixes in alongside this massive refactoring was impossible to resist. One of the problems was that most of their routes were camelCase
URLs, but userupdate
was not. So they’d fixed it. It was a minor change, and it worked in testing. So what was happening?
Well, there was a legacy authorization database. It was one of those 15 backend servers, and it ran no web code, and thus wasn’t touched by our submitter’s refactoring. Despite their web layer having copious authorization and authentication code, someone had decided back in the olden days, to implement that authorization and authentication in its own database.
Not every request went through this database. It impacted new sessions, but only under specific conditions. But this database had a table in it, which listed off all the routes. And unlike the web code, which used regular expressions for checking routes, and were case insensitive, this database did a strict equality comparison.
The fix was simple: update the table to allow userUpdate
. But it also pointed towards a deeper, meaner target for future refactoring: dealing with this sometimes required (but often not!) authentication step lurking in a database that no one had thought about until our submitter’s refactoring broke something.
ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.