Patrick's dev notes - PatrickF1/GraceTunes GitHub Wiki
Replacing Unicorn with Puma
- https://medium.com/finc-engineering/switching-to-puma-3a91575297af
- https://about.gitlab.com/blog/2020/07/08/migrating-to-puma-on-gitlab
- https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server
Evaluating thread safety
Puma workers are threads rather than processes so we have to deal with thread safety. Potential problem spots: class variables (they are prefixed with @@
), class methods (def self.method
), global variables ($global_var
), and instance methods where the instance lives on past a single web request.
- https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#thread-safety-tips
- https://www.youtube.com/watch?v=kufXhNkm5WU&t=1990s
- https://stackoverflow.com/questions/53825135/rails-class-method-is-thread-safe
- https://stackoverflow.com/questions/13715404/are-ruby-class-methods-thread-safe
Conclusion: all the code is thread safe!
Exploring the session cookie store
Learning about sessions
- https://www.justinweiss.com/articles/how-rails-sessions-work
- https://guides.rubyonrails.org/security.html#session-storage
- https://gist.github.com/wildjcrt/6359713fa770d277927051fdeb30ebbf
Decrypting a local _GraceTunes_session
cookie in rails console
def verify_and_decrypt_session_cookie(cookie, secret_key_base = Rails.application.secret_key_base)
config = Rails.application.config
cookie = CGI::unescape(cookie)
salt = config.action_dispatch.authenticated_encrypted_cookie_salt
encrypted_cookie_cipher = config.action_dispatch.encrypted_cookie_cipher || 'aes-256-gcm'
serializer = ActiveSupport::MessageEncryptor::NullSerializer
key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
key_len = ActiveSupport::MessageEncryptor.key_len(encrypted_cookie_cipher)
secret = key_generator.generate_key(salt, key_len)
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: encrypted_cookie_cipher, serializer: serializer)
session_key = config.session_options[:key].freeze
encryptor.decrypt_and_verify(cookie, purpose: "cookie.#{session_key}")
end
=> :verify_and_decrypt_session_cookie
verify_and_decrypt_session_cookie('Sp9vfigwKc534EHjUFVpfMAJvyADLCu4TrDzrDLR5KU%2BMnAhpqCQZRrouMmc6iLtDwj47LqWlddTXQgxayQFlOubjoRK1JtDoW8kCthiZDWBp%2BCDYVfIipPF4SGMaLpX8NZ7MhBVZCUYjTACGIW%2FHOmOH3f0pjVcFjrDR9tl%2BgDGZD7qNor0HmWmzu6PcLtoQ8zIJBNWKKMrOfW7Dy9T7h8mhHq
VAX7ptyTITUpVte%2BQn9hxZJhCqGjo4qL2Z4YcgUeqSPUNKF8HEv3VEsCAzSZfCF6RCL3PqVwfWMAnQ4DnnlrLKM7owoTknmZAF84326UCf6B%2BcwmQS0Os4p3k7TqCznD5hmE6AZyYpuqs9I51nvPXtLzvswV93mpm1ReB%2F9QxRKI%3D--JybhuWBnWpxnuEHA--5g%2BHgLzbirEMkTpqm77OVQ%3D%3D')
=> "{\"session_id\":\"42193dc27a12fca399509e6b6bb29751\",\"_csrf_token\":\"EIqxBDqpUX1Bxmig1WXekbCExnhq4LP5D1JDYfoI8tA\",\"user_email\":\"[email protected]\"}"
How does session cookie expiration work since the cookie doesn't contain a timestamp?
The session ID is generated using SecureRandom.hex which generates a random hex string
- it seems the expiration being configured by CookieStore is merely an
Expires
attribute on the Set-Cookie response header - this means session cookies, out of the box, are highly vulnerable to replay attacks without extra work to expire cookies on the server
- Stackoverflow confirmation
Setting up Heroku custom domains
- How do custom domains work in DNS terms? Heroku sets up a DNS target that provides the A records (which has the actual IP addresses) and and then you configure your domain to alias a subdomain to that DNS target using a CNAME record.
- Why didn't the custom domain work until I enabled automated SSL certs? because the Rails app had
config.force_ssl = true
, which redirected it to https port 443 and without certs, there was no point in Rails listening on that port. - After setting
config.force_ssl = false
, how come the http page would still automatically redirect to https? Because by that point, Chrome's security features had cached that the domain uses https and automatically redirects to https. Deleting that cache HTTPS cache entry worked. https://superuser.com/questions/565409/how-to-stop-an-automatic-redirect-from-http-to-https-in-chrome - The Heroku DNS Target (e.g. vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com) is what is called the canonical name, right? yes
- How come I can't load the Heroku DNS targets in my browser? Quoting https://help.heroku.com/3EUIOIVB/why-can-t-i-access-herokudns-com-cname-endpoints-in-my-browser
herokudns.com endpoints are not directly browsable and are only to be used as CNAME targets for DNS.
The Heroku routing layer uses the Host header from the client to ensure the correct application responds to a request -
this needs to be set to the value of your custom domain (if you have one set up) to route to the correct application.
As a result, you cannot access your application by visiting the herokudns.com address directly.
- When DNS resolvers cache a domain that is aliased to another one through a CNAME, it caches the other domain name and not the IP address(es), right? Yes. I see from https://serverfault.com/questions/718434/does-a-client-cache-the-ip-of-a-cname-dns-request-or-the-other-domain and that the CNAME record is cached separately from the A record
dig gracetunes.acts2.network
; <<>> DiG 9.10.6 <<>> gracetunes.acts2.network
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10088
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;gracetunes.acts2.network. IN A
;; ANSWER SECTION:
gracetunes.acts2.network. 172794 IN CNAME vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com.
vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com. 4 IN A 18.205.36.100
vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com. 4 IN A 52.204.242.176
vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com. 4 IN A 54.157.58.70
vast-raccoon-s1vn7089sg8wubmhaeqmak9g.herokudns.com. 4 IN A 54.162.128.250
;; Query time: 71 msec
;; SERVER: 100.100.100.100#53(100.100.100.100)
;; WHEN: Wed Nov 15 10:41:10 PST 2023
;; MSG SIZE rcvd: 182
- how do I see how long the TTL on the cached DNS records? It's the number in the second column in the
dig
output, which is in seconds - how do I see how the steps the DNS resolver takes?
dig +trace domain.name
- why don't NS records contain the IP addresses of the name server? So that if the IP of the name server changes, the NS admin only need to update one DNS record, and it doesn't affect the users of the NS at all. But yes, it does require the users to do an extra lookup. https://superuser.com/questions/64255/why-are-domain-names-rather-than-ip-addresses-used-in-name-server-records