Skip to content

Download public key from S3 with AWS credential#47

Merged
waisingyiu merged 7 commits intomainfrom
wsy/load-public-settings-using-aws-sdk
Jul 15, 2025
Merged

Download public key from S3 with AWS credential#47
waisingyiu merged 7 commits intomainfrom
wsy/load-public-settings-using-aws-sdk

Conversation

@waisingyiu
Copy link
Contributor

@waisingyiu waisingyiu commented Jul 3, 2025

Context

We are looking to address the FSBP high severity security issue about the S3 bucket "pan-domain-auth-settings" not blocking public access.

From S3 access log, we spotted that there were successful, unauthenticated requests to read some objects in this bucket from our applications.

We found that the public settings files there (which were S3 objects with a suffix "settings.public" were configured to allow public access and this client library, pan-domain-node, read these objects via direct HTTP requests without any AWS credential.

Therefore, we have to change the way we access these public setting file before we can turn on "Block all public access" option on the bucket.

What does this change?

This pull request changes the library to read the public key file via AWS SDK S3 client instead of making direct HTTP requests. To achieve this, it makes the following changes:

  1. Add an optional argument, 'localDev', to the main class 'PanDomainAuthentication` to indicate whether the applicant is running locally or in AWS.
  2. Load the AWS credential based on the localDev argument.
  3. Create S3 client object and use it to download the public key from S3 bucket.
  4. Pull in the AWS SDK bundle for S3 and credential providers.
  5. Update some dependencies so that they can work with the AWS SDK.

How to test

I modified the app image-url-signing-service to pull in the local version of this library and started the app locally.

  • get redirected to login.gutools page for authentication when I open a page on the local image URL signing service.
  • get back to the image-url-signing-service page successfully after authentication.

@changeset-bot
Copy link

changeset-bot bot commented Jul 3, 2025

🦋 Changeset detected

Latest commit: cc5ce32

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@guardian/pan-domain-node Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@waisingyiu waisingyiu force-pushed the wsy/load-public-settings-using-aws-sdk branch from f598f89 to 99c0a2b Compare July 7, 2025 09:57
@waisingyiu waisingyiu force-pushed the wsy/load-public-settings-using-aws-sdk branch from 99c0a2b to b0f394f Compare July 8, 2025 09:10
@waisingyiu waisingyiu changed the title Use aws sdk to load public settings file Download public key from S3 with AWS credential Jul 8, 2025
@waisingyiu waisingyiu marked this pull request as ready for review July 8, 2025 09:32
@waisingyiu waisingyiu requested a review from a team as a code owner July 8, 2025 09:32
Copy link
Contributor

@SHession SHession left a comment

Choose a reason for hiding this comment

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

These changes make sense, have they been tested using npm-link on any of the consuming apps?

Looks like a most consumer may be a few version behind so it may be some work to get the up-to-date: https://www.npmjs.com/package/@guardian/pan-domain-node?activeTab=versions

src/panda.ts Outdated
s3Client: S3;

constructor(cookieName: string, region: string, bucket: string, keyFile: string, validateUser: ValidateUserFn) {
constructor(cookieName: string, region: string, bucket: string, keyFile: string, validateUser: ValidateUserFn, localDev : boolean = false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we update the README with some detail about this change? What local credentials and level of access will people need for this to work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, I'll update the README.

At the moment, we grant the GetObject permission on the bucket to any IAM under a (fairly broad) list of AWS accounts (such as composer, cms-fronts, mobile etc). So the execution environment requires credential of any IAM users under these account. I'll add this to the README.

src/panda.ts Outdated
this.publicKey = fetchPublicKey(region, bucket, keyFile);
const standardAwsConfig = {
region: region,
credentials: localDev? fromIni({ profile: LOCAL_PROFILE }): fromNodeProviderChain(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Presumably any environment running this in AWS will need to be configured with read access to S3 bucket. In some cases will require cross-account permissions to be set up. This would be worth mentioning in the documentation.

@waisingyiu
Copy link
Contributor Author

These changes make sense, have they been tested using npm-link on any of the consuming apps?

Looks like a most consumer may be a few version behind so it may be some work to get the up-to-date: https://www.npmjs.com/package/@guardian/pan-domain-node?activeTab=versions

yes, I tested the changes locally with these consuming apps: ten_four-quiz-builder and image URL signing. They were on version 0.4 and so, yes, I need to make changes for bumping their pan-domain-node to 1.0.

@SHession
Copy link
Contributor

These changes make sense, have they been tested using npm-link on any of the consuming apps?
Looks like a most consumer may be a few version behind so it may be some work to get the up-to-date: https://www.npmjs.com/package/@guardian/pan-domain-node?activeTab=versions

yes, I tested the changes locally with these consuming apps: ten_four-quiz-builder and image URL signing. They were on version 0.4 and so, yes, I need to make changes for bumping their pan-domain-node to 1.0.

This is great! I was planning to do some testing myself, but looks like you're way ahead of me.

README.md Outdated
Comment on lines 44 to 46
The library requires AWS credential to read the public key files from the S3 bucket `pan-domain-auth-settings` in `Workflow` account. Please ensure that the execution environment has AWS credential for an IAM profile that has read access to the bucket.

Currently, the bucket has been configured to allow access from any IAM users under a (fairly broad) list of AWS accounts (such as composer, cms-fronts, mobile etc). Please get in touch with Workflow and Collaboration team if you need to get the read permission on the `pan-domain-auth-settings` bucket for your AWS acount.
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth clarifying your description a bit. Technically we are using a bucket in the Workflow account. However, this package is publicly available and could be utilised by others who are using Panda in a non-guardian environment. Therefore we can't assume that consumers of this library are going to be using the Guardian bucket.

To avoid this assumption, we could remove references to the specific account and bucket and just mention bucket / object access is required. We could also link to the Panda documentation if that would be useful: https://github.com/guardian/pan-domain-authentication.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A very good point. I've updated the readme to make it more general.

I've also added an argument to PanDomainAuthentication for the AWS profile name, which is used when the application is running locally. Previously I assumed that it was Workflow.

@waisingyiu waisingyiu requested a review from SHession July 14, 2025 14:51
src/panda.ts Outdated
s3Client: S3;

constructor(cookieName: string, region: string, bucket: string, keyFile: string, validateUser: ValidateUserFn, localDev : boolean = false) {
constructor(cookieName: string, region: string, bucket: string, keyFile: string, validateUser: ValidateUserFn, localDev : boolean = false, localProfile?: string) {
Copy link
Contributor

@SHession SHession Jul 15, 2025

Choose a reason for hiding this comment

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

I hadn't thought about this but it makes sense to change this too!

I was wondering if we should have a single argument to control both. For example localDev being an optional string, which when provided overrides the nodeProviderChain. I'm not quite sure on this, but two arguments which are co-dependent also feels a little clunky.

Maybe the argument should be an optional credentials type for greater flexibility?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A good idea! I've made the change in the last commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks great! Can we update the README to reflect this too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I've updated the README.

@waisingyiu waisingyiu requested a review from SHession July 15, 2025 09:59
@waisingyiu waisingyiu force-pushed the wsy/load-public-settings-using-aws-sdk branch 2 times, most recently from d48e64b to 325284a Compare July 15, 2025 13:13
@waisingyiu waisingyiu force-pushed the wsy/load-public-settings-using-aws-sdk branch from 325284a to cc5ce32 Compare July 15, 2025 13:17
Copy link
Contributor

@SHession SHession left a comment

Choose a reason for hiding this comment

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

Looks great!

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.

Load the public settings file using AWS SDK instead of direct HTTP requests

2 participants