class Google::Cloud::Gemserver::Authentication
Manages the permissions of the currently logged in user with the gcloud sdk.
Attributes
The project id of the Google
App Engine project the gemserver was deployed to. @return [String]
Public Class Methods
Creates the Authentication
object and sets the project id field.
# File lib/google/cloud/gemserver/authentication.rb, line 41 def initialize @proj = Configuration.new[:proj_id] end
Public Instance Methods
Generates an access token from a user authenticated by gcloud.
@return [String]
# File lib/google/cloud/gemserver/authentication.rb, line 67 def access_token return unless can_modify? scope = ["https://www.googleapis.com/auth/cloud-platform"] auth = Google::Auth.get_application_default scope auth.fetch_access_token! end
Checks if the currently logged in user can modify the gemserver i.e. create keys.
@return [Boolean]
# File lib/google/cloud/gemserver/authentication.rb, line 50 def can_modify? user = curr_user owners.each do |owner| return true if extract_account(owner) == user end editors.each do |editor| return true if extract_account(editor) == user end puts "You are either not authenticated with gcloud or lack access" \ " to the gemserver." false end
@private Implicitly checks if the account that generated the token has edit permissions on the Google
Cloud
Platform project by issuing a redundant update to the project (update to original settings).
@param [String] The authentication token generated from gcloud.
@return [Boolean]
# File lib/google/cloud/gemserver/authentication.rb, line 82 def validate_token auth_header token = auth_header.split.drop(1)[0] appengine_url = "https://appengine.googleapis.com" endpoint = "/v1/apps/#{@proj}/services/default?updateMask=split" version = appengine_version token split = { "split" => { "allocations" => { version.to_s => 1 } } } res = send_req appengine_url, endpoint, Net::HTTP::Patch, token, split if check_status(res) op = JSON.parse(res.body)["name"] wait_for_op appengine_url, "/v1/#{op}", token true else false end end
Private Instance Methods
@private Fetches the latest version of the deployed Google
App Engine instance running the gemserver (default service only).
@param [String] The authentication token generated from gcloud.
@return [String]
# File lib/google/cloud/gemserver/authentication.rb, line 114 def appengine_version token appengine_url = "https://appengine.googleapis.com" path = "/v1/apps/#{@proj}/services/default" res = send_req appengine_url, path, Net::HTTP::Get, token fail "Unauthorized" unless check_status(res) JSON.parse(res.body)["split"]["allocations"].first[0] end
@private Checks if a request response matches a given status code.
@param [Net::HTTPResponse] reponse The response from a request.
@param [Integer] code The desired response code.
@return [Boolean]
# File lib/google/cloud/gemserver/authentication.rb, line 188 def check_status response, code = 200 response.code.to_i == code end
@private Fetches the active account of the currently logged in user.
@return [String]
# File lib/google/cloud/gemserver/authentication.rb, line 226 def curr_user raw = run_cmd "gcloud auth list --format json" JSON.load(raw).map do |i| return i["account"] if i["status"] == "ACTIVE" end abort "You are not authenticated with gcloud" end
@private Fetches members with a role of editor that can access the gemserver.
@return [Array]
# File lib/google/cloud/gemserver/authentication.rb, line 209 def editors members "roles/editor" end
@private Parses a gcloud “member” and removes the account prefix.
@param [String] acc The member the account is extracted from.
@return [String]
# File lib/google/cloud/gemserver/authentication.rb, line 240 def extract_account acc acc[acc.index(":") + 1 .. acc.size] end
@private Fetches the members with a specific role that have access to the Google
App Engine project the gemserver was deployed to.
@return [Array]
# File lib/google/cloud/gemserver/authentication.rb, line 197 def members type yml = YAML.load(run_cmd "gcloud projects get-iam-policy #{@proj}") yml["bindings"].select do |member_set| member_set["role"] == type end[0]["members"] end
@private Fetches members with a role of owner that can access the gemserver.
@return [Array]
# File lib/google/cloud/gemserver/authentication.rb, line 218 def owners members "roles/owner" end
@private Runs a given command on the local machine.
@param [String] args The command to be run.
# File lib/google/cloud/gemserver/authentication.rb, line 248 def run_cmd args `#{args}` end
@private Sends a request to a given URL with given parameters.
@param [String] dom The protocol + domain name of the request.
@param [String] path The path of the URL.
@param [Net::HTTP] type The type of request to be made.
@param [String] token The authentication token used in the header.
@param [Hash] params Additional parameters send in the request body.
@return [Net::HTTPResponse]
# File lib/google/cloud/gemserver/authentication.rb, line 138 def send_req dom, path, type, token, params = nil uri = URI.parse dom http = Net::HTTP.new uri.host, uri.port http.use_ssl = true if dom.include? "https" req = type.new path req["Authorization"] = Signet::OAuth2.generate_bearer_authorization_header token unless type == Net::HTTP::Get if params req["Content-Type"] = "application/json" req.body = params.to_json end end http.request req end
@private Waits for a project update operation to complete.
@param [String] dom The domain and protocol of the request.
@param [String] path The path of the request containing the operation ID.
@param [String] token The authorization token in the request.
@param [Integer] timeout The length of time the operation is polled.
# File lib/google/cloud/gemserver/authentication.rb, line 165 def wait_for_op dom, path, token, timeout = 60 start = Time.now loop do if Time.now - start > timeout fail "Operation at #{path} failed to complete in time" else res = send_req dom, path, Net::HTTP::Get, token if JSON.parse(res.body)["done"] == true break end sleep 1 end end end