-
-
Save gpocentek/bd4c3fbf8a6ce226ebddc4aad6b46c0a to your computer and use it in GitHub Desktop.
import re | |
import sys | |
import requests | |
import gitlab | |
URL = 'https://gitlab.com' | |
SIGN_IN_URL = 'https://gitlab.com/users/sign_in' | |
LOGIN_URL = 'https://gitlab.com/users/sign_in' | |
session = requests.Session() | |
sign_in_page = session.get(SIGN_IN_URL).content | |
for l in sign_in_page.split('\n'): | |
m = re.search('name="authenticity_token" value="([^"]+)"', l) | |
if m: | |
break | |
token = None | |
if m: | |
token = m.group(1) | |
if not token: | |
print('Unable to find the authenticity token') | |
sys.exit(1) | |
data = {'user[login]': 'login_or_email', | |
'user[password]': 'SECRET', | |
'authenticity_token': token} | |
r = session.post(LOGIN_URL, data=data) | |
if r.status_code != 200: | |
print('Failed to log in') | |
sys.exit(1) | |
gl = gitlab.Gitlab(URL, api_version=4, session=session) |
if you get the error "bytes expected not str", apply this fix
for l in sign_in_page.decode().split('\n'):
Or
sign_in_page = session.get(SIGN_IN_URL).text
which uses requests' encoding detection mechanism.
@MikeTuffy thank you so much matte! Exactly what I needed.
Could you please add an open-source license for this gist?
Code with no particular license is covered by Githubs Terms of Service:
https://docs.github.com/en/github/site-policy/github-terms-of-service#d-user-generated-content
So fork and relicense, or fork and continue with the ToS as license.
@MikeTuffy Thank you for your ldap Post! It works! :-)
This procedure no longer works. Instead of a sign-in page, I get a page titled "Checking your Browser - GitLab" that does not contain an authentication token.
I've been using and updating this code for some automation tasks since version Gitlab 12. Here are some notable changes I've had to make as Gitlab is updated:
Gitlab 14.5.2
'profile/personal_access_tokens'
has moved to:
'-/profile/personal_access_tokens'
Gitlab 15.1.3
The authenticity token on the personal_access_tokens page has moved into a meta tag called "csrf-token". The created-personal-access-token field is gone, but I found that you could potentially use BS to pull the token value out of a button with the "title="Copy personal access token". I opted to grab the value from the "new_token" value which was already present in the response:
page_tokens = session.get('/'.join((URL, '-/profile/personal_access_tokens')))
private_token = None
if page_tokens.ok:
root = bs4.BeautifulSoup(page_tokens.text, "html5lib")
token = root.find_all("meta", attrs={'name': 'csrf-token'})[0]['content']
body = {
"personal_access_token[name]": 'mytoken',
"personal_access_token[scopes][]": 'api',
'authenticity_token': token
}
response = session.post('/'.join((URL, '-/profile/personal_access_tokens')), data=body)
if response.ok:
private_token = response.json()['new_token']
if not private_token:
sys.exit(1)
session.headers.update({'Private-Token': private_token})
gl = gitlab.Gitlab(URL, api_version=4, session=session)
Hello nice work.
Today in 16.8.1-ce.0, i had to fetch again the CSRF token because the login create a new gitlab session.
So here the process that worked for me :
- Get a first CSRF in an anon session
- Try to login
- Receive a 302 to /
- Get the CSRF again from the 302 location
- Use gitlab
In additionnal note, i changed the regex to <meta\s+name="csrf-token"\s+content="([^"]+)"
. It simply avoid the use of beautiful soup.
if you get the error "bytes expected not str", apply this fix