Skip to content

Conversation

@snickell
Copy link
Contributor

@snickell snickell commented Aug 10, 2024

Get a "secure context" in Dev/Drone without HTTPS

We currently use URLs like http://localhost-studio.code.org because we have internal logic that's keyed to what domain name you use. Alternatively we could use a URL like http://studio.code.org.localhost, which are special to browsers and would automatically give us a secure context and enable a number of modern web features, from SharedArrayBuffer to Service Workers and Web RTC.

Basically: using .localhost domains in dev is a way of getting access to HTTPS gated browser features without actually needing HTTPS setup.

Fixes #60328

The alternative way to get a secure context is to run as HTTPS in dev, but getting that working locally has been hard, and using an adhoc to do dev is pretty hard too. In actual practice, I think the burden of using https in local dev has meant we just don't use those features. For example, we are not using the most straightforward way to stop a python program because it uses SharedArrayBuffer: #60320

Here's a list of some modern web features we're missing out on that require a secure context:

  1. WebRTC
  2. MediaDevices.getUserMedia() (access camera and mic)
  3. Service Workers
  4. WebAssembly.compileStreaming()
  5. Geolocation API
  6. Notification API
  7. Payment Request API
  8. Credential Management API
  9. Web Bluetooth API
  10. WebUSB API
  11. Clipboard API (write access)
  12. Storage Access API
  13. Push API
  14. Permissions API
  15. SharedArrayBuffer
  16. Subresource Integrity (SRI)
  17. Performance.now() with high resolution

Considerations

  • What about cross-domain cookies?
    • Will this setup work for that? cross pegasus/dashboard sign in works at least
    • Will our root domain be org.localhost then?
      • Should we be considering using code.localhost instead of code.org.localhost? Then our root domain would be code.localhost, which makes more sense.
      • Will that give us cross-domain cookies?
  • What about HTTPS dev? Can we use .localhost domains for that?
  • What if you have override_dashboard or override_pegasus set to an old-style URL? A: include a comment in the announcement to devs
  • Browser support in dev
    • Chrome (and probably derivatives like Arc): secure context
    • Firefox: secure context
    • Edge: secure context
    • Safari doesn't support .localhost automatically, you have to add domains to /etc/hosts, but then they DO get the secure context
      • Do we use localhost-style URLs with Safari on drone?

Services that might need updates to allowed domain lists

  • Java Builder, do we need to add .localhost domains on the AWS side? (github)
  • What about OneTrust? Do we need to register .localhost domains with it or something? Does it even operate on dev? one trust source code links
  • What about Cloudfront?
  • SauceLabs: initial research suggests saucelabs doesn't have an allowed domains list, they just use the tunnel
  • Applitools Eyes?
  • CDO::Metrics? e.g. see test_metrics.rb
  • FontAwesome
    • Need to update CORS policy on DSCO S3 (design system) bucket
      image
  • Google Maps
  • MapboxGL
  • S3 Bucket CORS policies
  • OAuth providers
    • Google
    • Microsoft
    • Facebook
    • Clever
    • Investigate: Canvas (may need updating settings with them?), Schoolology (may not currently work locally?)

Specific code impacts of concern

  • Route53, be sure we won't impact e.g. CodprojectsCertificate (github

Developer Transition Impact

  • Have to login again to local dev without auto password fill, and either make a new account (and maybe lose levelbuilder perms, etc) or do a manual password lookup in your password manager (chrome/1pass/apple/whatever).
  • Autocomplete of historical URLs in the browser URL bar will be wrong, lose convenience of muscle memoried dev URLs
  • What if you have dashboard_override or pegasus_override set to an old-style url? this should be very rare, but might be worth planning for the few people who might have this for whatever reason?
  • Remembering the new url until its muscle memory slightly breaks context, mild workaround, now print URL at dashboard startup:
image

TODO

  • JS tests pass
  • Unit tests pass
  • UI tests pass
  • Drone passes
  • Is there a way to run a test server-like instance??

@snickell
Copy link
Contributor Author

snickell commented Aug 10, 2024

Cookies

Ruby

JS/TS

@snickell
Copy link
Contributor Author

snickell commented Aug 10, 2024

Domains of interest

  • localhost-studio.code.org => studio.code.org.localhost
  • localhost.code.org => code.org.localhost
  • localhost.codeprojects.org => codeprojects.org.localhost
  • localhost.hourofcode.com => hourofcode.com.localhost
  • Any domains missing?

Maybe don't need to work?

  • localhost.csedweek.org => csedweek.org.localhost, doesn't seem to be on staging?
    image

Wildcards:

  • From def canonical_hostname in cdo.rb:
    -return "#{name}.#{domain}" if ['console', 'hoc-levels'].include?(name):
    • console.code.org?
    • hoc-levels.code.org?
    • return "localhost#{sep}#{domain}" if rack_env?(:development) || ci_webserver?
      • I think this means Drone uses localhost-studio.code.org?

@snickell
Copy link
Contributor Author

snickell commented Aug 10, 2024

Papercuts

On http://studio.code.org.localhost:3000/home:

@snickell
Copy link
Contributor Author

snickell commented Aug 11, 2024

It's Alive!

Basic "mostly works" has been achieved. There's still broken URLs, missing assets, etc, but its mostly functional.

Pegasus works:

image

Dashboard works:

image

Cross-pegasus dashboard cookies work

I think? they have to for sign in right?

Cross Pegasus <=> Dashboard links seem to work, the ones I've tested:

image

Hour of Code works:

image

HTTPS works:

image

@snickell
Copy link
Contributor Author

snickell commented Aug 11, 2024

One failed unit test from ruby, its about shared cookies:

  test_shared_cookie_domain                                       FAIL (0.00s)
Minitest::Assertion:         Expected: "code.org"
          Actual: "code.org.localhost"
        /drone/src/pegasus/test/test_request.rb:22:in `block in test_shared_cookie_domain'
        /drone/src/pegasus/test/test_request.rb:20:in `each'
        /drone/src/pegasus/test/test_request.rb:20:in `test_shared_cookie_domain'

I just confirmed on Chrome, the way it works right now is most of our code.org cookies are set on the def shared_cookie_domain (request.rb on github).

Do any of these cookies need to be shared?

Notice how localhost-studio.code.org and code.org have exactly the same .code.org cookies? That's shared_cookie_domain at work:
image

hourofcode.com is basically alone in its own cookie world:

  • hourofcode.com. ==> .hourofcode.com

But all these domains map to the same shared cookie domain .code.org:

  • code.org ==> .code.org
  • staging.code.org ==> .code.org
  • test.code.org ==> .code.org
  • levelbuilder.code.org ==> .code.org
  • localhost.code.org ==> .code.org
  • studio.code.org ==> .code.org
  • test-studio.code.org ==> .code.org
  • localhost-studio.code.org ==> .code.org

Do we actually want to share cookies between environments?

This test makes sure that happens, and it breaks because code.org.localhost cannot share a cookie domain with code.org. But.... isn't that a good thing? Notice we had to namespace our primary session cookies? Is this basically a vestigial complexification? Do we need to track google analytics users between test-studio.code.org and code.org? Between studio.code.org and localhost-studio.code.org? We're not using this feature.

In general I want as strong a boundary between my staging/test/prod as possible! This is an anti-feature, and we've gone out of way to enable it (it doesn't do this by default).

Proposal 1: (default) we use a non-sahred cookie for .localhost domains

Everything the same as above but:

boo.localhost ==> boo.localhost

Currently fixed this way by: 25ead00 and followup to simplify c5d1893

Proposal 2: we break away from shared cookies entirely

And fix this test to reflect it:

  • code.org ==> .code.org # preserve sessions and tracking on code.org prod
  • test.code.org ==> test.code.org
  • levelbuilder.code.org ==> levelbuilder.code.org
  • test-studio.code.org ==> test-studio.code.org
  • studio.code.org.localhost ==> studio.code.org.localhost

@cat5inthecradle
Copy link
Contributor

I'm curious about the code.org.localhost vs code.localhost question. What's the reasoning for one over the other?

@snickell snickell changed the title Convert dev to .localhost domains Use .localhost domains for a secure context w/o HTTPS Sep 10, 2024
@snickell
Copy link
Contributor Author

This works with Sauce Connect v5, but not with Sauce Connect v4, so this PR is now blocking on: #60333

@snickell snickell mentioned this pull request Oct 28, 2024
2 tasks
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 http://studio.code.org.localhost to get a secure context in dev

2 participants