Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

fix(perforce) Fix support for p4breaker workaround scripts#63611

Merged
pjlast merged 10 commits into
mainfrom
petrilast-src-441-perforce-broker-workaround-no-longer-works
Jul 10, 2024
Merged

fix(perforce) Fix support for p4breaker workaround scripts#63611
pjlast merged 10 commits into
mainfrom
petrilast-src-441-perforce-broker-workaround-no-longer-works

Conversation

@pjlast

@pjlast pjlast commented Jul 3, 2024

Copy link
Copy Markdown
Contributor

When we switched to JSON parsing for p4 protects commands (adding the -Mj -ztag flags) we accidentally broke support for a work around some customers use when it comes to perforce permissions.

The p4broker workaround

Sourcegraph requires a user with access to the perforce protects table. In perforce, this user needs super access, which is a hard pill to swallow for certain security setups. Customers can work around this by using Helix Broker and creating a filter for the Sourcegraph user. The filter intercepts the protects command and executes a different script that performs the p4 protects command as a super user, and then sends the output of that command back as a message.

The issue

When executing the script and sending the output of the script back as a message, it is technically no longer a Perforce server response. It's a debug message meant to be displayed to the user. Without the -Mj -ztag flags, this is not much of an issue, because the output is displayed directly anyways. However, with the JSON flags the p4 CLI now JSON encodes the debug message, NOT the actual server response, and it encodes it as {"data": "{message}", "level": 0}, with all of the response dumped in {message}. This is not what Sourcegraph expects, but it is still valid JSON, so it leads to no errors and zero perms for the user.

The fix

The fix comes in two parts: this PR and changes to the script being used.

The script

  1. The filter script needs to add the -Mj -ztag flags to its p4 protects command as well
  2. The filter scipt needs to base64-encode the output it receives. This is because the p4 CLI strips messages of all quotation marks ("). See here at the end of the "Filter programs" section. Stripping the quotes breaks the JSON encoding. By base64-encoding the JSON output, we can decode it again on Sourcegraph.

This PR

This PR makes some changes to the way we decode the protects response. First we try to decode it the normal way. If the decoded response has empty fields, we assume it to be a broker response and try decoding the "data" field instead. If this succeeds, we URL-decode the "data" field, and then we try to decode the result of that as before.

Test plan

Unit test added for a URL-encoded JSON response.

Changelog

  • Fixed an issue where Sourcegraph would no longer be able to decode Perforce permissions if p4broker is used, provided that the filter script gets adjusted as well.

@cla-bot cla-bot Bot added the cla-signed label Jul 3, 2024
@github-actions github-actions Bot added team/product-platform team/source Tickets under the purview of Source - the one Source to graph it all labels Jul 3, 2024
@pjlast pjlast requested a review from a team July 3, 2024 12:16
return nil, errors.Wrap(err, "failed to unmarshal protect line")
}

if parsedLine.DepotFile == "" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if we should turn this on with an env var - as it requires that script to be correctly deployed anyways.

In addition, is there something we could do here to make sure things that don't parse properly (i.e. this json thing that doesn't contain any data) will not cause all perms to be dropped, and fail instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could always simply return an error if DepotFile is empty. I don't know what we would do with an empty DepotFile field anyways?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah I guess that’s good, better than this silent failure we had here

return nil, errors.New("not a valid protects response")
}

protectsJson, err := url.QueryUnescape(parsedBrokerResponse.Data)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

have you tried to fix the broker script already? was urlencoding in there easy? If not, maybe worth trying an alternative format like base64 which would be very easy to handle and be sure it handles non-ascii characters well, too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I adjusted the broker script. URL encoding was easy. But I'm switching to base64 now simply because I like it more

@pjlast pjlast enabled auto-merge (squash) July 10, 2024 15:37
}

type perforceBrokerJSONProtect struct {
Data string `json:"data"` // URL encoded JSON

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This comment is wrong - and if you use []byte here I think you can save on the decode string part further down

@pjlast pjlast merged commit 23128d1 into main Jul 10, 2024
@pjlast pjlast deleted the petrilast-src-441-perforce-broker-workaround-no-longer-works branch July 10, 2024 15:39
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla-signed team/product-platform team/source Tickets under the purview of Source - the one Source to graph it all

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants