Logging in from the API

I’m currently working on a GitLab-enabled app. For the purpose of testing the app, I’d like to programmatically:

  1. start a fresh GitLab from Docker [DONE]
  2. create an admin account [DONE]
  3. get the token for that admin account [?]
  4. using that token, create users, projects, check my workflow, etc.

I… just don’t get how to make step 3 happen.

Any suggestion?

If you want to do it graphically, then log into the web interface with the admin user. Then under the top right hand corner, click the avatar for the admin user and then Settings from the menu. Then on the left side of the screen click Access Tokens and create an access token with the appropriate access you require.

If you are wanting to create that access token by using the Gitlab API instead, then check here:

https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token

that token can then later be utilised to authenticate with instead of the user password. However, assuming you wish to create that access token via API, then you would need to authenticate initially using the user password.

I can’t do anything graphically, as I’m running all this from a configuration script.

Yes, that’s the API I’m planning to use. However, this API already requires a token.

My entire problem is how to get that first token.

If it’s a new install, then there is no token. You have to create it first, and to do that you need to authenticate, which means your only option is to use a password.

I have created the admin password by setting

gitlab_rails['initial_root_password'] = foobar

in my GITLAB_OMNIBUS_CONFIG

This is the only password at this stage, as we’re freshly installed. How do I proceed from here?

After changes of gitlab.rb:

gitlab-ctl reconfigure

to activate the changes.

Then, check the API documentation from the link above as it explains how you can use the create access-token API commands to create a particular access-token for a particular user (by using their user id). The documentation will have all the info you need, but you will need to check/test the API calls to make sure it works as required.

Yes, this is the very documentation I’ve been perusing for a few days. Unless I misread the documentation completely, the example given is

curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/personal_access_tokens"

which seems to indicate that this requires an access token (for the admin) to be used.

Am I missing something?

If I am not missing something, I’m back to the problem: “I have a password, I need to get a token”.

You need to make the curl URL request using your root login and the password you assigned, so instead of the --header option with ACCESS-TOKEN field to authenticate, to create the initial token you would need to put the username/password in the URL field, so:

https://root:foobar@mygitlab.domain.com/api/v4/users/42/personal_access_tokens

obviously along with the remaining parameters prior to the url itself, just without the header time.

You will then get results back, like from the docs, showing something like:

{
    "id": 3,
    "name": "mytoken",
    "revoked": false,
    "created_at": "2020-10-14T11:58:53.526Z",
    "scopes": [
        "api"
    ],
    "user_id": 42,
    "active": true,
    "expires_at": "2020-12-31",
    "token": "ggbfKkC4n-Lujy8jwCR2"
}

and you can pull the token from the API reponse and then stop utilising the root login in the URL at this point forward and use the access-token which should have been created under the userid for admin account.

Remember, until you have an access-token you cannot user the --header field with an access-token. And since you can’t create it via the web interface, then you need to use a username/password in your API requests until that initial access-token exists.

The above url is an example, so you need to change “42” to whatever the userid is of your admin account. And the userid you can get also making an API query, but again, you have to provide username/password to check that as well until you create the access-token.

Ahah!

That’s what I’ve been looking for all along, thanks!

Out of curiosity, where is that documented?

Without searching API documents, not sure if it’s shown there, but it does exist here:

https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html#pushing-to-a-remote-repository

this is obviously mirroring repositories, but you can see the URL required along with username:password@ or even can be username:token@ in the URL as well since both will work.

Generally with curl though, Gitlab API examples show using --headers, but I don’t have a working example for that to work with username/password values. But I expect it’s possible, just a case of using the appropriate parameters.

Generally all API’s will work in a similar way, be it Gitlab, or others.

Unfortunately

GET http://root:foobar@localhost:7776/api/v4/users

returns a 403 Forbidden - Not authorized to access /api/v4/users

and

POST http://root:foobar@localhost:7776/api/v4/users

similarly returns a 401.

Not sure if that’s because this authentication scheme isn’t supported here or because of any other problem.

I guess they just developed it to allow only auth via OAUTH or access token, since all there examples seem to use access-tokens and nothing else, like the examples from the docs above. To be honest I can understand it, as placing a username/password in a URL isn’t so secure, as access tokens can always be revoked. It was a long-shot, since I couldn’t find it in their API docs, only for mirroring repositories, so it seems in some places a username/password is allowed in the URL, just not with the API.

Unfortunately, that doesn’t help you, which means you need to login to the web interface and at least create an initial access-token to use. Unless OAUTH would help you after integrating it, but I don’t use it so can’t help with that.

In other words, to do this, I need to replicate the start page’s forms.
Not much fun :frowning:

Thanks for the help.

1 Like

I found a solution!

The idea is to use the gitlab rails console:

$ gitlab-rails console "
user = User.create();
user.name = '$(USERNAME)';
user.username = '$(USERNAME)';
user.password = '$(PASSWORD);
user.confirmed_at = '01/01/1961';
user.admin = true;
user.email = '$(USERNAME)@example.com';
user.save!;
puts 'User created';

token = user.personal_access_tokens.create(scopes: [:api], name: 'Automation token');
token.set_token('$(TOKEN)');
token.save!;
puts 'Token created';
"

And since I’m doing this in docker-compose:

$ docker-compose -p $MYPROJECT -f $MYCONFIG exec gitlab gitlab-rails console $THE_STRING_ABOVE

Since GitLab startup is pretty slow, this call fails for the first ~30 seconds. So far, I’m using a backoff-and-retry loop until it works. Interestingly, this works before the API becomes accessible (the API itself takes another ~30 seconds to be up and running).

With token $(TOKEN), I can now access a few APIs (possibly all, but I haven’t finished testing).

2 Likes

Wow nice one :slight_smile:

Yep, with API scope you should be able to do everything that the user account has access to.