Skip to content
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

fix(admin-panel): Fix remote group resolution #12871

Merged
merged 1 commit into from
May 13, 2022

Conversation

dschom
Copy link
Contributor

@dschom dschom commented May 12, 2022

Because

  • The remote group was not resolved correctly which rendered the admin panel useless.

This pull request

  • Targets the correct header, 'remote-groups', which was previously 'REMOTE-GROUP'. This small thing was really the crux of the problem.
  • Does some cleanup and removes magic strings for header keys.
  • Makes the AdminPanelGuard aware of the current environment. This ended up being the bulk of the changes, and was necessary since user groups are environment specific, and therefore the guard needs to be able to distinguish this. I.e. A user user could be part of an ldap group that has admin privileges on stage, but not part of the ldap group that has admin privileges on prod.
  • Resolves the correct user group for the current environment. For example, when both stage and prod ldap groups are provided in the remote-groups header, we must resolve the group that’s most appropriate for the current environment.
  • Introduces a hook for GuardContext. Now that the AdminPanelGuard is aware of the current environment it is essentially contextual and should be accessed from a hook.

Issue that this pull request solves

Closes: #12744

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).

@dschom dschom force-pushed the FXA-5027-fix-remote-group-resolution branch 3 times, most recently from 380d4cc to 2f363eb Compare May 13, 2022 00:43
@@ -15,8 +21,8 @@ describe('ClientConfig', () => {
user,
});
const injectedHtml = ClientConfig.injectIntoHtml(html, {
'REMOTE-GROUP': remoteHeader,
'oidc-claim-id-token-email': user.email,
[USER_GROUP_HEADER]: remoteHeader,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanup - avoid magic strings

});
});

it('handles multiple remote group headers', () => {
Copy link
Contributor Author

@dschom dschom May 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a more realistic test. Turns out a large number of ldap groups can be passed on this header.


it('renders without imploding', () => {
const guard = new AdminPanelGuard(AdminPanelEnv.Prod);
Copy link
Contributor Author

@dschom dschom May 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guards are now aware of the environment. This is needed to determine the case when a user might be in a stage ldap group but not in a prod ldap group (or vice versa).


const App = ({ config }: { config: IClientConfig }) => {
const [guard, setGuard] = useState<AdminPanelGuard>(config.guard);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since guards are now aware of the environment, they technically need to be part of the context.

@@ -8,12 +8,12 @@ The [GraphQL playground](https://www.apollographql.com/docs/apollo-server/testin

The playground requires an `oidc-claim-id-token-email` authorization header. In production this is supplied through an nginx header after LDAP credentials, which have been verified but in development, a dummy email should be supplied in the bottom left-hand corner of the GQL playground labeled "HTTP Headers":

In addition a `REMOTE-GROUP` header must also be set to indicate the user's LDAP group membership. Again, in production this will be set by nginx, but in development, a dummy value must be supplied.
In addition a `remote-groups` header must also be set to indicate the user's LDAP group membership. Again, in production this will be set by nginx, but in development, a dummy value must be supplied.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we were targeting the wrong header. This was the main source of the issue.

@@ -26,7 +26,9 @@ it('renders each field as expected', () => {

screen.getByText(subscription.productName);
screen.getByText(subscription.status);
expect(screen.getAllByText('1970-01-19 @', { exact: false })).toHaveLength(4);
expect(screen.getAllByText(/1970-01-1[89] @/, { exact: false })).toHaveLength(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was tricky. The test was failing and I thought I was going crazy cause clearly it passed at some point. Turns out the issue is that dateFormat is taking the users timezone into account. So depending on where you are you might get a different result. For example:

> const dateFormat = require('dateformat')
undefined
> dateFormat(new Date(1583259953), 'UTC:yyyy-mm-dd @ HH:MM:ss Z') 
'1970-01-19 @ 07:47:39 UTC'
> dateFormat(new Date(1583259953), 'yyyy-mm-dd @ HH:MM:ss Z') 
'1970-01-18 @ 23:47:39 PST'

In a PST timezone, 1583259953, would have renders with 1970-01-18 date and the subsequent test would pass. This makes the check a bit more flexible. Alternatively we could render everything in UTC. Not sure what's best.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never used dateFormat. moment is used in fxa-auth-server though (and in fxa-shared), could be worth looking into/switching as an alternative?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that'd be nice to consistent about this. @LZoog any thoughts here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're only using dateFormat in the admin-panel, agreed, we could follow a follow up to replace it with moment; less dependencies WFM.

@dschom dschom changed the title WIP fix(admin-panel): Fix remote group resolution May 13, 2022
@dschom dschom marked this pull request as ready for review May 13, 2022 01:08
@dschom dschom requested a review from a team as a code owner May 13, 2022 01:08
@dschom dschom requested review from LZoog, millmason and xlisachan and removed request for millmason May 13, 2022 14:04
@clouserw
Copy link
Member

You pre-seeded this PR with a few good notes here. If you'll indulge me a drive-by comment: Your comments are what I'd like to see if I were modifying this file 6 months down the road. Eg. figuring out why a test regex is [89] instead of 9 feels like the kind of thing a person could rabbit-hole on, or read an inline comment and think "oh yeah, good point about timezones."

Thanks for the patch!

@dschom dschom force-pushed the FXA-5027-fix-remote-group-resolution branch from 2f363eb to f1e91d7 Compare May 13, 2022 15:21
Copy link
Contributor

@xlisachan xlisachan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🎉

packages/fxa-admin-panel/src/App.tsx Outdated Show resolved Hide resolved
@@ -26,7 +26,9 @@ it('renders each field as expected', () => {

screen.getByText(subscription.productName);
screen.getByText(subscription.status);
expect(screen.getAllByText('1970-01-19 @', { exact: false })).toHaveLength(4);
expect(screen.getAllByText(/1970-01-1[89] @/, { exact: false })).toHaveLength(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never used dateFormat. moment is used in fxa-auth-server though (and in fxa-shared), could be worth looking into/switching as an alternative?

Because:
- The remote group was not resolved correctly which rendered the admin panel useless.

This Commit:
- Targets the correct remote group header, 'remote-groups', which was previously 'REMOTE-GROUP'.
- Does some clean up and removes magic starings.
- Makes the guard aware of the current environment. This ended up being the bulk of the changes, and was necessary nice certain
- Handles edge case where both stage and ldap groups are provided in remote-groups header. AdminPanelGuard is now aware of the current environment.
- Introduces a hook for GuardContext. This hook provides a guard instance, which is aware of the current environment.
@dschom dschom force-pushed the FXA-5027-fix-remote-group-resolution branch from f1e91d7 to 6339b0b Compare May 13, 2022 16:21
@dschom dschom merged commit 9c14190 into main May 13, 2022
@dschom dschom deleted the FXA-5027-fix-remote-group-resolution branch June 15, 2022 01:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to access staging admin panel (not in a group)
4 participants