Class: ApceraAuth

Inherits:
Object
  • Object
show all
Defined in:
lib/apcera_api_helper.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target = "", bearer = "") ⇒ ApceraAuth

Returns a new instance of ApceraAuth.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/apcera_api_helper.rb', line 47

def initialize(target = "", bearer = "")
	# If a target or bearer is passed in, use that, otherwise, try to figure it out		
	#
	cache_credentials = false
	
	if (target.nonblank? || bearer.nonblank?)
		@target = target
		@bearer = bearer
	else
		cache_credentials = true
		
		@cache_file_path = File.expand_path("~/.apcera_api")

		if !File.writable?(File.expand_path("~/"))
			puts "Cache File #{@cache_file_path} not writable, falling back to tmp"
			@cache_file_path = "/tmp/.apcera_api"
		end
		
		cached_fields = {}
		if (File.exists?(@cache_file_path))
			cached_fields = JSON.parse(File.read(@cache_file_path))
		end
	
		# First, get the target.  If it isn't in the cache or env, prompt for it
		#
		if (!cached_fields.has_key?("target") || cached_fields["target"] == "")
		
			default = "http://demo.proveapcera.io"
		
			value = prompt_for_value("Enter the domain name for the cluster [#{default}] : ").delete!("\n")

			if value == ""
				value = default
			end
			cached_fields["target"] = value
		end
		
		# Just need to make sure that these are set when done
		#
		@target = cached_fields["target"]
	end

	# Build the paths
	#
	parts = @target.split(/[:\/]/)

	@scheme = parts.first
	@domain = parts.last

	@api_host = "api.#{@domain}"
	
	# Have to be running against a 2.x cluster or later for this to work.  Older
	# Clusters want the auth host to be "auth.xxx" not or "gauth.xxx"
	#
	@auth_host = "gauth.#{@domain}"
	@base_api_url = "#{scheme}://#{@api_host}"
	
	@base_auth_url = "#{scheme}://#{@auth_host}"
	
	# if the $HTTP_URI is set then we are in app_token mode, and auth is done.
	#
	if (ENV.key?("HTTP_URI"))
		puts "HTTP_URI is set [#{ENV.key("HTTP_URI")}], app_token mode"
		return
	end
	
	if (target.nonblank? || bearer.nonblank?)
		@bearer = bearer
	else
		# We need to find it.
		#
		if (ENV.key?("APC_REFRESH_TOKEN"))
			puts "WARNING: Using refresh token from environment"
			cached_fields["refresh_token"] = ENV["APC_REFRESH_TOKEN"]
		end

		if (!cached_fields.has_key?("refresh_token") || cached_fields["refresh_token"] == "")
			response = RestClient.get("#{@base_auth_url}/v1/oauth2/device/google/getcode")
			code = JSON.parse(response)

			ApceraApiHelper.notice "go to \n\n#{code['verification_url']}\n\n and enter code #{code['user_code']}\n\n"
	
			# This stuff only works on the mac
			#
			system("echo #{code['user_code']} | pbcopy")
			system("open #{code['verification_url']}")

			value = prompt_for_value "Press Y when completed: "

			if value.delete!("\n").casecmp("Y") != 0
				ApceraApiHelper.notice "Error, giving up."
				exit
			end

			device_code = code['device_code']

			redeemed_url = "#{@base_auth_url}/v1/oauth2/device/google/redeemed"

			obj = {:device_code => device_code}

			refresh_token_wrapper = JSON.parse(RestClient.post(redeemed_url, obj.to_json, {:content_type => :json}))
			cached_fields["refresh_token"] = refresh_token_wrapper["refresh_token"]
		end	
		
		# If the token isn't there, or is expired, refresh it
		#
		if !cached_fields.has_key?("token") || cached_fields["token"] == "" || Time.parse(cached_fields["expires"]) < Time.now
			refresh_url = "#{@base_auth_url}/v1/oauth2/device/google/refresh"

			refresh_token_wrapper = {:refresh_token => cached_fields["refresh_token"], :token_type => "GOOGLE_REFRESH" }
			begin
				refresh_resp = RestClient.post(refresh_url, refresh_token_wrapper.to_json, {:content_type => :json})
			rescue Exception => e
				refresh_resp = RestClient.post(refresh_url, refresh_token_wrapper.to_json, {:content_type => 'application/json'})
			end
			
			refreshed_token = JSON.parse(refresh_resp)
			
			cached_fields["token"] = "Bearer #{refreshed_token['access_token']}"
			cached_fields["expires"] = Time.now + refreshed_token["expires_in"].to_i			
		end
		@bearer = cached_fields["token"]			
	end
	
	@token_prefix = @bearer.split.first
	@token = @bearer.split.last

	if (cache_credentials)	
		File.write(cache_file_path, JSON.pretty_generate(cached_fields))
	end

end

Instance Attribute Details

#api_hostObject (readonly)

Returns the value of attribute api_host.



38
39
40
# File 'lib/apcera_api_helper.rb', line 38

def api_host
  @api_host
end

#auth_hostObject (readonly)

Returns the value of attribute auth_host.



39
40
41
# File 'lib/apcera_api_helper.rb', line 39

def auth_host
  @auth_host
end

#base_api_urlObject (readonly)

Returns the value of attribute base_api_url.



40
41
42
# File 'lib/apcera_api_helper.rb', line 40

def base_api_url
  @base_api_url
end

#base_auth_urlObject (readonly)

Returns the value of attribute base_auth_url.



41
42
43
# File 'lib/apcera_api_helper.rb', line 41

def base_auth_url
  @base_auth_url
end

#bearerObject (readonly)

Returns the value of attribute bearer.



30
31
32
# File 'lib/apcera_api_helper.rb', line 30

def bearer
  @bearer
end

#cache_file_pathObject (readonly)

This is situational



45
46
47
# File 'lib/apcera_api_helper.rb', line 45

def cache_file_path
  @cache_file_path
end

#domainObject (readonly)

Returns the value of attribute domain.



36
37
38
# File 'lib/apcera_api_helper.rb', line 36

def domain
  @domain
end

#schemeObject (readonly)

Returns the value of attribute scheme.



37
38
39
# File 'lib/apcera_api_helper.rb', line 37

def scheme
  @scheme
end

#targetObject (readonly)

Want to update this to check for HTTP_URI. If that is set, don’t do ANY auth.

These are the bare minimum



29
30
31
# File 'lib/apcera_api_helper.rb', line 29

def target
  @target
end

#tokenObject (readonly)

These are calculated from the above



34
35
36
# File 'lib/apcera_api_helper.rb', line 34

def token
  @token
end

#token_prefixObject (readonly)

Returns the value of attribute token_prefix.



35
36
37
# File 'lib/apcera_api_helper.rb', line 35

def token_prefix
  @token_prefix
end

Instance Method Details

#prompt_for_value(*args) ⇒ Object



180
181
182
183
# File 'lib/apcera_api_helper.rb', line 180

def prompt_for_value(*args)
    print(*args)
    gets
end

#to_sObject



185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/apcera_api_helper.rb', line 185

def to_s
	body  = "target            [#{@target}]\n"
	body += "bearer            [#{@bearer}]\n"
	body += "token             [#{@token}]\n"
	body += "token_prefix      [#{@token_prefix}]\n"
	body += "domain            [#{@domain}]\n"
	body += "scheme            [#{@scheme}]\n"
	body += "api_host          [#{@api_host}]\n"
	body += "auth_host         [#{@auth_host}]\n"
	body += "base_api_url      [#{@base_api_url}]\n"
	body += "base_auth_url     [#{@base_auth_url}]\n"
	body += "cache_file_path   [#{@cache_file_path}]\n"
end