Skip to content

Commit

Permalink
apiserver: enforce code formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
FooBarWidget committed Aug 21, 2024
1 parent 58b3ac3 commit 28bd300
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 35 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/apiserver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ jobs:
BUNDLE_PATH: vendor/bundle
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
BUNDLE_WITH: ci
BUNDLE_CLEAN: "true"

- name: Check code formatting with Rufo
run: bundle exec rufo --check .
working-directory: apiserver
env:
BUNDLE_WITH: ci

- name: Create tarball
run: >
tar
Expand Down
14 changes: 9 additions & 5 deletions apiserver/Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
source 'https://rubygems.org'
source "https://rubygems.org"

ruby '>= 3.2'
ruby ">= 3.2"

gem 'puma'
gem 'sinatra', '~> 4'
gem 'jwt'
gem "puma"
gem "sinatra", "~> 4"
gem "jwt"

group :ci, optional: true do
gem "rufo"
end
58 changes: 29 additions & 29 deletions apiserver/app.rb
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
# frozen_string_literal: true

require 'jwt'
require 'net/http'
require 'sinatra/base'
require "jwt"
require "net/http"
require "sinatra/base"

class App < Sinatra::Base
GITHUB_ACTIONS_OIDC_ISSUER_URL = 'https://token.actions.githubusercontent.com'
GITHUB_JWKS_URL = 'https://token.actions.githubusercontent.com/.well-known/jwks'
EXPECTED_AUDIENCE_CLAIM = 'backend.fullstaqruby.org'
GITHUB_ACTIONS_OIDC_ISSUER_URL = "https://token.actions.githubusercontent.com"
GITHUB_JWKS_URL = "https://token.actions.githubusercontent.com/.well-known/jwks"
EXPECTED_AUDIENCE_CLAIM = "backend.fullstaqruby.org"

get '/' do
content_type 'text/plain'
get "/" do
content_type "text/plain"
"ok\n"
end

post '/admin/upgrade_apiserver' do
authorize!('fullstaq-ruby/infra', environment: 'deploy')
post "/admin/upgrade_apiserver" do
authorize!("fullstaq-ruby/infra", environment: "deploy")

if !system('sudo', 'systemctl', 'restart', 'apiserver-deployer')
if !system("sudo", "systemctl", "restart", "apiserver-deployer")
$stderr.puts "Failed to upgrade API server: #{$?}"
end

# Restart apiserver after 5 seconds so that 'systemctl' itself
# gets a chance to run instead of being immediately killed.
Thread.new do
$stderr.puts 'Restarting API server in 5 seconds...'
$stderr.puts "Restarting API server in 5 seconds..."
sleep 5
if !system('sudo', 'systemctl', 'restart', 'apiserver')
if !system("sudo", "systemctl", "restart", "apiserver")
$stderr.puts "Failed to restart API server: #{$?}"
end
end

"ok\n"
end

post '/admin/restart_web_server' do
authorize!('fullstaq-ruby/server-edition', environment: 'deploy')
post "/admin/restart_web_server" do
authorize!("fullstaq-ruby/server-edition", environment: "deploy")

# Restart web server after 5 seconds so that this request's
# response can reach the client.
Thread.new do
$stderr.puts 'Restarting web server in 5 seconds...'
$stderr.puts "Restarting web server in 5 seconds..."
sleep 5
if !system('sudo', 'systemctl', 'restart', 'caddy')
if !system("sudo", "systemctl", "restart", "caddy")
$stderr.puts "Failed to restart web server: #{$?}"
end
end
Expand All @@ -54,51 +54,51 @@ class App < Sinatra::Base

def authorize!(repository, expected_claim_values = {})
token = extract_authz_token
halt 401, 'Missing or invalid Authorization header' unless token
halt 401, "Missing or invalid Authorization header" unless token

begin
decoded_token = verify_github_jwt(token)
if !valid_claims?(decoded_token[0], repository, expected_claim_values)
halt 403, 'Invalid authorization token claims'
halt 403, "Invalid authorization token claims"
end
rescue JWT::DecodeError => e
halt 403, "Invalid authorization token: #{e.message}"
end
end

def extract_authz_token
authz_header = request.env['HTTP_AUTHORIZATION']
authz_header&.start_with?('Bearer ') ? authz_header.split(' ', 2).last : nil
authz_header = request.env["HTTP_AUTHORIZATION"]
authz_header&.start_with?("Bearer ") ? authz_header.split(" ", 2).last : nil
end

def verify_github_jwt(token)
JWT.decode(token, nil, true, {
algorithms: ['RS256'],
algorithms: ["RS256"],
jwks: fetch_github_jwks,
iss: GITHUB_ACTIONS_OIDC_ISSUER_URL,
verify_iss: true,
aud: EXPECTED_AUDIENCE_CLAIM,
verify_aud: true,
verify_iat: true,
leeway: 60 # 1 minute leeway for clock skew
leeway: 60, # 1 minute leeway for clock skew
})
end

def fetch_github_jwks
@github_jwks ||= begin
resp = Net::HTTP.get_response(URI(GITHUB_JWKS_URL))
halt 500, 'Failed to fetch GitHub JWKS' unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
resp = Net::HTTP.get_response(URI(GITHUB_JWKS_URL))
halt 500, "Failed to fetch GitHub JWKS" unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
end

def valid_claims?(claims, repository, expected_claim_values)
if !claims['sub'].start_with?("repo:#{repository}:") || claims['repository'] != repository
if !claims["sub"].start_with?("repo:#{repository}:") || claims["repository"] != repository
$stderr.puts "Invalid repository claim: expected=#{repository.inspect}, actual=#{JSON.pretty_generate(claims)}"
return false
end

if claims['runner_environment'] != 'github-hosted'
if claims["runner_environment"] != "github-hosted"
$stderr.puts "Invalid runner_environment claim: expected=github-hosted, actual=#{JSON.pretty_generate(claims)}"
return false
end
Expand Down
2 changes: 1 addition & 1 deletion apiserver/config.ru
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
require './app'
require "./app"
run App.new

0 comments on commit 28bd300

Please sign in to comment.