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

feat: sign traffic between RS and AS #31

Merged
merged 4 commits into from
Mar 10, 2024
Merged

Conversation

termontwouter
Copy link
Collaborator

@termontwouter termontwouter commented Mar 6, 2024

This PR contains a lot of changes to do a simple thing: sign requests between RS and AS, and check those signatures.

It was a messy trial-and-error development process, so my apologies for the lack of more granular commits, and the rough edges in some places.

Closes #29

Signed-off-by: Wouter Termont <[email protected]>
Copy link
Contributor

@woutslabbinck woutslabbinck left a comment

Choose a reason for hiding this comment

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

I tested it both with node v20 and with v18 and the test flows work.
Though there is a need to have .nvmrc and the docs pointing to the same version for consistency, if that is fixed I'll approve.

Something entirely else, I've found a bug with the enforcement flow (some missing exports). I'll make a new branch to fix this

@woutslabbinck woutslabbinck mentioned this pull request Mar 7, 2024
@termontwouter termontwouter merged commit a90d9be into main Mar 10, 2024
3 checks passed
@termontwouter termontwouter deleted the feat/sign-rs-as-traffic branch March 10, 2024 12:24

try {
const permissionEndpoint = (await fetchUmaConfig(issuer)).permission_endpoint;
return fetchPermissionTicket(requestedModes, permissionEndpoint, pat);
endpoint = (await this.fetchUmaConfig(issuer)).permission_endpoint;
} catch (e: any) {
throw new Error(`Error while retrieving ticket: ${(e as Error).message}`);

Choose a reason for hiding this comment

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

FYI CSS has a createErrorMessage utility function.

protected options: UmaVerificationOptions = {},
) {}

public async signedFetch(url: string, request: RequestInit & Omit<SignRequest, 'url'>): Promise<Response> {

Choose a reason for hiding this comment

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

To understand, this is the replacement for the current PAT right? Is the plan to eventually somehow have 1 key per data owner? Or one per server and see the entire server as a single owner?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Correct. Plans are not clear yet. UMA says PAT per owner, GNAP says HTTP Message Signatures between servers (similar to this implementation). Not sure yet about my preference. Any thoughts?

Choose a reason for hiding this comment

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

Having it be server-side definitely seems easier, as otherwise users somehow have to be responsible for providing their own PAT. Unless they let the server generate it for them, but at that point you might as well have just one for the server. If you trust the server to store all your data, I don't really see the point in having a personal PAT.

}

private process(): void {
this.processing = true;

Choose a reason for hiding this comment

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

Why have these? As the loop and shifting is sync, I don't think it's necessary, as no other calls will be completed until the backlog has been emptied.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ha, I guess you're right! Being too careful...

Comment on lines +3 to +6
* Any object of which a status can be changed.
*/
export interface StatusDependant<T> {
changeStatus(status: T): Promise<void>,

Choose a reason for hiding this comment

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

Isn't that almost any object? 😅 Very subjective but name feels weird to me. I'm thinking more of something like setState and as interface name StateMachine or something similar?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I know, terrible name 😆 I was wondering for the CSS: do you prefer we just implement this specifically for the Fetchers, or do we keep this and change the name to something better?

Choose a reason for hiding this comment

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

I'm ok with a generic interface as not all fetchers will need this, and there might be other components in the future that also depend on something similar. But I would prefer a better name 😀

import type { StatusDependant } from './StatusDependant';

/**
* A {@link ServerConfigurator} that maps events of a {@link Server} so a status,

Choose a reason for hiding this comment

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

Suggested change
* A {@link ServerConfigurator} that maps events of a {@link Server} so a status,
* A {@link ServerConfigurator} that maps events of a {@link Server} to a status,

const trigger = new EventEmitter();
const result = new Promise<Response>(resolve => {
trigger.on(PROCESS, () => {
this.fetcher.fetch(...args).then(response => resolve(response))

Choose a reason for hiding this comment

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

Suggested change
this.fetcher.fetch(...args).then(response => resolve(response))
this.fetcher.fetch(...args).then(resolve)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

🤔 is this necessary, or are you instinctively applying ESlint rules? 😄

Choose a reason for hiding this comment

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

It just felt wrong to not at least mention it 😉


async fetch(...args: FetchParams): Promise<Response> {
const trigger = new EventEmitter();
const result = new Promise<Response>(resolve => {

Choose a reason for hiding this comment

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

Minor optimization, but might be nicer to already check the status here and immediately return the fetch without the promise/eventemitter if the fetcher is active.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

True, I even thought about it, but I was lazy. Will do for CSS PR ...

@termontwouter
Copy link
Collaborator Author

@joachimvh review and merge must have crossed, because I only see this now due to notifications ... Will take most things up somewhere else, but feel free to still reply here.

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.

Use actual keys between RS and AS
3 participants