Dec 05, 2014 Code spelunking to build a CF Plugin
This is a quick "how to" for how Long found the information he needed to build the cf info plugin.
Following a trail of breadcrumbs
Determine the requirements:
- Print the currently targeted org and space
- Print the API version and endpoint
- Print the user id of the current user (similar to
whoamiin *nix OSes).
Fulfilling the requirements:
This information comes from
cf target, so first we'll take a look in
- Line 83 in
target.goprints the current session information as reported from
- Line 196 in
- Line 175 of
configis actually from the
- There are a few *.go files in the
core_configpackage, but searching this repository for
UserEmailshows that the method is defined in
config_repository.goon lines 199-204.
UserEmailrequires a struct, called
ConfigRepositoryis built from the
NewRepositoryFromPersistormethod. (You can tell this both by the
return &ConfigRepositoryon line 23 or by noting that
NewRepositoryFromPersistorreturns all the fields needed by the struct - i.e.
NewRepositoryFromPersistoris returned from the method above it,
How to get the file path? Searching for
CF_HOME (environmental variable storing the home directory) shows that it is defined in
config_helpers.go. Now what to do with that information:
DefaultFilePathis defined using either
$HOMEis the user's home directory in Unix environments).
- As a sanity check, if you are using a Unix environment run
echo $CF_HOME. If it is non-empty, then run
less $CF_HOME/.cf/config.json. If it is empty, run
less $HOME/.cf/config.json. You should see the configuration file that
cf targetuses to report the org, space, and API information (there is other information in there as well).
- Recall that
UserEmailis defined in lines 199-204 of
config_repository.go. You can see that
config_repository.goalso has the other information we wish to pull - the org (
OrganizationFields), space (
SpaceFields), API endpoint (
ApiEndpoint), and API version (
What to do with all of that
Basically everything in reverse. You supply the default file path, which is
config.json has the org, space, API endpoint, API version, and Access Token. The existing
cf code decodes the Access Token and the
UserEmail method extracts the email address from that information. Everything is just pulled directly from the repository you just defined.
Addendum: What is going on to get that email anyway?
Let's take a quick look in
config.json. The 7th line should be the Access Token, which should look similar to this:
"AccessToken": "bearer eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI3NzI2ZDE2MS1hNWUzLTQwZjMtYTEzYy00OTlmMDNjOTBhZGIiLCJzdWIiOiI2Y2I5MTA0Yy1hZTMxLTQxYTMtOGQ4MS1jYjUxZjg0MTk5ZTMiLCJzY29wZSI6WyJjbG91ZF9jb250cm9sbGVyLmFkbWluIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwiY2xvdWRfY29udHJvbGxlci53cml0ZSIsIm9wZW5pZCIsInBhc3N3b3JkLndyaXRlIiwic2NpbS5yZWFkIiwic2NpbS53cml0ZSJdLCJjbGllbnRfaWQiOiJjZiIsImNpZCI6ImNmIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6IjZjYjkxMDRjLWFlMzEtNDFhMy04ZDgxLWNiNTFmODQxOTllMyIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsImlhdCI6MTQxNzgxMTU3NywiZXhwIjoxNDE3ODEyMTc3LCJpc3MiOiJodHRwczovL3VhYS41NC4xNzQuMjI5LjExOS54aXAuaW8vb2F1dGgvdG9rZW4iLCJhdWQiOlsic2NpbSIsIm9wZW5pZCIsImNsb3VkX2NvbnRyb2xsZXIiLCJwYXNzd29yZCJdfQ.XNaYq8rxpvwWx9kySIDqbKs0BuyeOMMwAPb5YQaT-9MIyr3YalCE_2gTg-fl0xulj4u-VoNme3OGZ2T3tFFUfBKgo3U7R_pl5OpcaetKslbvKtYpne7N30KMQySMqVVVooGqlReoI_n5m5O7ZIASiG8P1QtwuVrZPkPhbjsGfBE",
Source: The above is the access token from a now-destroyed TryCF instance.
This is a JSON Web Token (JWT). You can read about JWT here. For now, all I really care about is that its structure is
<claims> section of the above token is between the two periods:
If you paste that information into Base 64 Decode, you can see the user's credentials - including the email field. (For TryCF the
admin.) If you paste in the above and decode it, you will see:
Feel free to try it with your own Access Token! :)