Download ssh public keys from GitHub and GitLab *with the comment field* - github

On both GitHub and GitLab, you can download a user's SSH public keys with a simple GET request to the URL https://server/username.keys, 
for example:
curl https://github.com/unclebob.keys
This gives:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArmmGWKZ8UAO6myYW94liK4oMNBen6Sl7r0QAb6Et0y1kwCIBeBrHZhsSFQBzw0H517FeML9d+fBMSShZloMvw5x8nLQq5kbi4+8JXC4+CwW505fipjFY4ABj60BZioZn4Hndf8bwmCwXDHVtjfUeBD8b+Sjn7VNQ123rd1t5TLYDShk+2I4ldDhxbkFRqBF1gz3is4BsngdsHQp5AuuFWmiD2FRDRZDACdUyL8fUIP6O/3TAGFNKP2CG6//8+XHbQOYUaJ9RkSAJ453dx2PwDdiIXJyIJRO/q8wqWyRhA94XtJ77zP9BMyrRVnMClYcQoc9WBBlocp519l9vsp6jyQ==  
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCoQ9S7V+CufAgwoehnf2TqsJ9LTsu8pUA3FgpS2mdVwcMcTs++8P5sQcXHLtDmNLpWN4k7NQgxaY1oXy5e25x/4VhXaJXWEt3luSw+Phv/PB2+aGLvqCUirsLTAD2r7ieMhd/pcVf/HlhNUQgnO1mupdbDyqZoGD/uCcJiYav8i/V7nJWJouHA8yq31XS2yqXp9m3VC7UZZHzUsVJA9Us5YqF0hKYeaGruIHR2bwoDF9ZFMss5t6/pzxMljU/ccYwvvRDdI7WX4o4+zLuZ6RWvsU6LGbbb0pQdB72tlV41fSefwFsk4JRdKbyV3Xjf25pV4IXOTcqhy+4JTB/jXxrF
Unfortunately, notice that there is no comment field at the end. 
On GitHub and GitLab the comment field is there in the system, you can view and edit in your profile to easily distinguish your multiple keys from each other.
But when accessing using this method, both GitHub and GitLab drop the comment field, for some reason.
Is there an easy way to get the public keys from these services? I'm aware of the REST APIs, but as far as I know they return JSON, which is not so convenient for example if I want to simply redirect the output of curl to append to an authorized_keys file. If I have to parse JSON, that adds more complexity to my scripts I'd like to avoid.

That seems a security issue, where the comment content might leak some possibly sensitive data if it were returned (since you can set any comment in there).
That is why the very specification of that "get keys" feature in GitLab does include:
it "should not render the comment of the key" do
get :get_keys, username: user.username
expect(response.body).not_to match(/dummy#gitlab.com/)
end

Related

Get a list of who has what access to git repositories

Using VSTS APIs, I'm trying to get a list of who has what access to each of our git repositories in VSTS.
I have the security namespaceId for Git and I pass this namespaceId to the Security -> Access Control List API described here:
https://www.visualstudio.com/en-us/docs/integrate/api/security/acls
GET https://xxxxxxxx.visualstudio.com/DefaultCollection/_apis/accesscontrollists/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/?api-version=1.0&recurse=true&includeExtendedInfo=false
Drilling into the response, I can see it is listing the permissions for each repo, along with ref and tags.
Each object contains "acesDictionary", which itself is an object with keys that look like this:
Microsoft.IdentityModel.Claims.ClaimsIdentity;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\emailaddress#example.com
How do I decipher a ClaimsIdentity? My first thought was that the UUID in the ClaimsIdentity is the UUID of the user in my VSTS project, but it is not. I know the email address is there so I suppose I could use that, but now I'm curious what the UUID in ClaimsIdentity represent. The VSTS API docs dont mention this.
Is Security -> Access Control Lists even the right place where I should be looking? My main goal is trying to get a list of who has what access to VSTS git repositories.
Through tech support, I was able to reach a Microsoft representative who shared with me that the documentation for mapping identity descriptors isn't available yet but will hopefully be released soon. In the meantime, there is an endpoint to crosswalk identity descriptors which looks something like this:
GET {account}.vssps.visualstudio.com/_apis/identities?descriptors={commaSeparatedDescriptorsList}&api-version={apiVersion}
Note that this call is made through SPS {account}.vssps.visualstudio.com and not through your account instance {account}.visualstudio.com
Using my example, it would look something like this (uuid obfuscated):
https://xxxxx.vssps.visualstudio.com/_apis/identities?descriptors=Microsoft.TeamFoundation.ServiceIdentity;ffead5b1-5121-4e0e-a439-bbecb4999eba:Build:c4bfb762-a246-46c9-ba9a-7e6c53386b11&api-version=4.0
Also, if the descriptor is of type Microsoft.IdentityModel.Claims.ClaimsIdentity, then you'll likely have escaped backslashes in your descriptor which you'll need to un-escape. For example, if you have:
"Microsoft.IdentityModel.Claims.ClaimsIdentity;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\someone#example.com"
You'll need to un-escape this descriptor so that it looks like this:
"Microsoft.IdentityModel.Claims.ClaimsIdentity;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\someone#example.com"

Invalid WebHook Signature

I created a GitHub Webhook function, copied and pasted the Function URL and GitHub Secret to the GitHub to the WebHook I created in GitHub and I keep getting the following error.
{"Message":"The WebHook signature provided by the 'X-Hub-Signature' header
field does not match the value expected by the 'GitHubWebHookReceiver'
receiver. WebHook request is invalid."}
Any ideas what I'm doing wrong?
OK, so it turns out the GitHub Secret from the Develop page matches the _master key from the Admin Keys (All Functions) keys on the Manage page.
When I used the default key from the Function Keys it started working. By the names of those sections that sounds like the key I actually want to use and maybe the portal is displaying the wrong one in the GitHub Secret field.
Not sure if this is the answer or a workaround.

GitHub Gist API patch doesn't work?

I am creating anonymous Gists using Postman. The Gists get created successfully but when I try to patch them, I get:
{
"message": "Not Found",
"documentation_url": "https://developer.github.com/v3/gists/#edit-a-gist"
}
The URL I am using is:
https://api.github.com/gists/14694f43065a32ec28ad
If I do a GET, it works fine. If I do a PATCH, I get an error message.
What's wrong here?
You can read and create anonymous gists, but you cannot edit them. If you want to create, read, update and delete, use authentication.
In the Authentication section, it says:
You can read public gists and create them for anonymous users without a token; however, to read or write gists on a user's behalf the gist OAuth scope is required.
You will get the same 404–Not found error if you just try to git push some commits into an anonymous gist.
$ git push
Username for 'https://gist.github.com': IonicaBizau
Password for 'https://IonicaBizau#gist.github.com':
remote: Repository not found.
fatal: repository 'https://gist.github.com/anonymous/5801....d2f/' not found
They don't even provide an edit button on the Gist page, for anonymous gists. They do have a Delete button associated with the IP (any user having the anonymous Gist link, being connected on the same network, assuming they get the same public ip, can delete the anonymous gist).
Otherwise you have to contact support for deleting the anonymous gist.

How to search for code in GitHub with GitHub API?

I'm trying to search for some piece of code using the GitHub API V3 given only the keyword, not limiting by user, organization, or repository.
For example, if I want to search for all pieces of code that contain the keyword "addClass", the results would be
https://github.com/search?q=addClass&type=Code&ref=searchresults without using GitHub API.
But how can I do the same thing through GitHub API? I tried https://api.github.com/search/code?q=addClass
It says "Must include at least one user, organization, or repository". How can I fix this?
You can do a code search without specifying a user/org/repo if you authenticate.
First, generate a personal access token for use for this purpose, from your Profile on GitHub's website:
Settings -> Developer Settings -> Personal Access Token -> Generate New Token (you can leave all access options unticked, since you're just using to make web requests)
Now, your original GET request will work and return results, if you append the token to it:
https://api.github.com/search/code?q=addClass&access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UPDATE: OCT 2021
As pointed out by a comment below, passing the token in via a query parameter (like above) is deprecated. You must now add it as an Authorization header.
e.g.
curl --location --request GET 'https://api.github.com/search/code?q=addClass +in:file +language:csharp' \
--header 'Authorization: Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
or in Python:
import requests
url = "https://api.github.com/search/code?q=addClass +in:file +language:csharp"
headers = {
'Authorization': 'Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
response = requests.request("GET", url, headers=headers)
print(response.text)
2020: As detailed in Mark Z.'s answer, using an authentication (Authorization': 'Token xxxx') allows for a code search.
get /search/code
You can use:
either a dedicated command-line tool like feinoujc/gh-search-cli
ghs code --extension js "import _ from 'lodash'"
or the official GitHub CLI gh, (after a gh auth login) as show in issue 5117:
gh api --method=GET "search/code?q=filename:test+extension:yaml+org:new-org"
Or even:
gh api --method=GET search/code -f q='filename:test extension:yaml org:new-org' \
--jq '.items[] | [.repository.full_name,.path,.sha] | #tsv'
That would get a line-based, tab-separated list of fields in this order: repo name, file path, git sha. (see gh help formatting)
2014 (original answer): That seems related to the new restriction "New Validation Rule for Beta Code Search API" (Oct. 2013)
In order to support the expected volume of requests, we’re applying a new validation rule to the Code Search API. Starting today, you will need to scope your code queries to a specific set of users, organizations, or repositories.
So, the example of the API search code mentions now:
Suppose you want to find the definition of the addClass function inside jQuery. Your query would look something like this:
https://api.github.com/search/code?q=addClass+in:file+language:js+repo:jquery/jquery
While Gihub does not currently support code search without repo, user, or organization (see VonC's answer), codesearch does index some sources from Github via the codesearch API, albeit with an API less fully featured out than Github's.
For example, to search for wget invocations indexed from Github, call
curl "https://searchcode.com/api/codesearch_I/?q=wget&src=2"
The optional src parameter picks the code source (e.g., Github, BitBucket) that should be searched, and you can find its integer value for a source by altering the parameters of faceted search in the codesearch UI. The current value of src for Github is 2.
You can verify that the returned results from the above example come from github.com by viewing the the repo property of results items.

Jenkins embeddable build status icon not shown

I want to use the Embeddable Build Status Plugin for Jenkins. I am using Cloudbees. I granted Job/ViewStatus permissions to the anonymous user. When I add the Markdown to the README.md no icon is shown. I tried both the protected and the unprotected link.
# protected
[![Build Status](https://johnjohndoe.ci.cloudbees.com/job/TypedPreferences/badge/icon)](https://johnjohndoe.ci.cloudbees.com/job/TypedPreferences/)
# unprotected
[![Build Status](https://johnjohndoe.ci.cloudbees.com/buildStatus/icon?job=TypedPreferences)](https://johnjohndoe.ci.cloudbees.com/job/TypedPreferences/)
By default DEV#cloud Jenkins instances are not visible, at all, to anonymous users. If you have configured role-based security and want anonymous users to have the selected roles, configure your system and check the box Enable read-only access for anonymous users.
Well, the question has been asked some time ago, but for others reaching it here, having the problem, that the image is still not shown within the Readme.md on GitHub/GitHub-Enterprise after performing the above mentioned configuration:
Make sure that both services are using the same protocol. In my case, we had GitHub-Enterprise running under HTTPS and Jenkins was running on HTTP.
The badge will not be shown in this case because of the possible security breach introduced by mixed content. You will find an appropriate error message in the console output of your browser (i.e. F12 in Chrome):
Mixed Content: The page at 'https://.../README.md' was loaded over HTTPS,
but requested an insecure image 'http://.../job/master/badge/icon'.
This request has been blocked; the content must be served over HTTPS.
It's of course quite obvious but something that can also be easily missed when searching on the wrong track.
I had an issue with space in the project name, so do not forget to replace spaces with %20
example:
[![Build Status](../Long%20Project%20Name/...)](.../Long%20Project%20Name/...)