How to get Gitlab runner registration token from command line? - terraform

I'm trying to deploy a Gitlab instance and runners ready with Terraform. The script creates both Gitlab and runners without any problem, but I don't know how to register the runners automatically after the creation.
Is there any way to get the registration token from command line? If it's possible I can register just calling external data source using Terraform.

The projects API endpoint response contains the runners_token key. You can use this to automatically fetch the runner tokens for any project.
You can then use that in a few ways. One way would be to have your runner registration script fetch the runner token itself such as with this example:
curl --fail --silent --header "Private-Token: ${GITLAB_API_TOKEN}" "https://$GITLAB_URL/api/v4/projects/${PROJECT}"
Or you could use the Gitlab Terraform provider's gitlab_project data source to fetch this from whatever is running Terraform and then inject it into the thing that runs the registration script such as a templated file:
data "gitlab_project" "example" {
id = 30
}
locals {
runner_config = {
runner_token = data.gitlab_project.example.runners_token
}
}
output "example" {
value = templatefile("${path.module}/register-runners.sh.tpl", local.runner_config)
}

Yes, you can.
The command has to be run on the server hosting your Gitlab instance. The line below will output the current shared runner token.
sudo gitlab-rails runner -e production "puts Gitlab::CurrentSettings.current_application_settings.runners_registration_token"
As others have mentioned, there is not API endpoint that currently allows this (there has been discussion over this for quite some time here. However, I find this solution satisfactory for my needs.

Credits for this answer go to MxNxPx. This script used to work (for me) two days ago:
GITUSER="root"
GITURL="http://127.0.0.1"
GITROOTPWD="mysupersecretgitlabrootuserpassword"
# 1. curl for the login page to get a session cookie and the sources with the auth tokens
body_header=$(curl -k -c gitlab-cookies.txt -i "${GITURL}/users/sign_in" -sS)
# grep the auth token for the user login for
# not sure whether another token on the page will work, too - there are 3 of them
csrf_token=$(echo $body_header | perl -ne 'print "$1\n" if /new_user.*?authenticity_token"[[:blank:]]value="(.+?)"/' | sed -n 1p)
# 2. send login credentials with curl, using cookies and token from previous request
curl -sS -k -b gitlab-cookies.txt -c gitlab-cookies.txt "${GITURL}/users/sign_in" \
--data "user[login]=${GITUSER}&user[password]=${GITROOTPWD}" \
--data-urlencode "authenticity_token=${csrf_token}" -o /dev/null
# 3. send curl GET request to gitlab runners page to get registration token
body_header=$(curl -sS -k -H 'user-agent: curl' -b gitlab-cookies.txt "${GITURL}/admin/runners" -o gitlab-header.txt)
reg_token=$(cat gitlab-header.txt | perl -ne 'print "$1\n" if /code id="registration_token">(.+?)</' | sed -n 1p)
echo $reg_token
However, as of today it stopped working. I noticed the second body_header variable is empty. Upon inspecting the gitlab-header.txt file, I noticed it contained:
You are being redirected.
Whereas I would expect it to be signed in at that point, with a gitlab-header.txt file that contains the respective runner registration token. I expect I am doing something wrong, however, perhaps there has been an update to the gitlab/gitlab-ce:latest package such that a change to the script is required.

Disclaimer, I am involved in creating that code
Here is a horrible but working Python boiler plate code that gets the runner token and exports it to a parent repository: https://github.com/a-t-0/get-gitlab-runner-registration-token.
Independent usage
It requires a few manual steps to set up, and then gets the GitLab runner registration token automatically (from the CLI with:). It requires Conda and Python however, and downloads a browser controller. So it is most likely wiser to look a bit better into the curl commands instead.
Integrated in parent [bash] repository
First install the conda environment, then activate it. After that, you can execute the function below automatically from the CLI (if you put that function in a file at path parent_repo/src/get_gitlab_server_runner_token.sh, assuming you have the credentials etc as specified in the Readme), with:
cd parent_repo
source src/get_gitlab_server_runner_token.sh && get_registration_token_with_python
This bash function gets the token:
get_registration_token_with_python() {
# delete the runner registration token file if it exist
if [ -f "$RUNNER_REGISTRATION_TOKEN_FILEPATH" ] ; then
rm "$RUNNER_REGISTRATION_TOKEN_FILEPATH"
fi
git clone https://github.com/a-t-0/get-gitlab-runner-registration-token.git &&
set +e
cd get-gitlab-runner-registration-token && python -m code.project1.src
cd ..
}
And here is a BATS test that verifies the token is retrieved:
#!./test/libs/bats/bin/bats
load 'libs/bats-support/load'
load 'libs/bats-assert/load'
load 'libs/bats-file/load'
source src/get_gitlab_server_runner_token.sh
source src/hardcoded_variables.txt
#test "Checking if the gitlab runner registration token is obtained correctly." {
get_registration_token_with_python
actual_result=$(cat $RUNNER_REGISTRATION_TOKEN_FILEPATH)
EXPECTED_OUTPUT="somecode"
assert_file_exist $RUNNER_REGISTRATION_TOKEN_FILEPATH
assert_equal ${#actual_result} 20
}

Related

How can I get userId after call create user api in keycloak?

I implemented keycloak in my node.js project and call following API for add user in keycloak:
{{keycloak_url}}/admin/realms/{{realm}}/users
This API works and I can add user in keycloak but I need userId in response to this API how can I get this, any alternative way for this
Thanks in advance
I believe there is another way to do this which will save you an extra request. If you take a look at the reponse headers when you create a user, you should find a field named "Location". It looks like this:
Location: http://keycloak_address/auth/admin/realms/realm/users/3a11cc77-9871-4f6e-805b-bf17ea79fa3a
In this case the value "3a11cc77-9871-4f6e-805b-bf17ea79fa3a" would be the new user's id.
Update: The /auth path was removed starting with Keycloak 17 Quarkus distribution. So you might need to remove the /auth from the endpoint calls presented on this answer.
You use the Keycloak Admin REST API endpoint GET /{realm}/users with the query parameter username. For instance:
GET "{{keycloak_url}}/auth/admin/realms/{{realm}}/users/?username={{username}}"
NOTE: In some Keycloak version it will return all the users with a username that matches {{username*}}. Therefore, additional filtering of the list might be necessary. For those using bash script I have uploaded to my repo one example on how to do filter currently. From the response you just need to extract the field id.
The approach pointed out first by #Sillas Reis allows to create the user and get its ID in a single call, which is more performant. However, I am not a fan of relying on non documented behavior. Nonetheless, for those using bash and curl that solution could look like the following:
Call the Keycloak Admin REST API with an access token from a user with the proper permissions. For now, I will be using the admin user from the master realm:
curl “https://${KEYCLOAK_HOST}/auth/realms/master/protocol/openid-connect/token” \
-d "client_id=admin-cli" \
-d "username=${ADMIN_NAME}” \
-d "password=${ADMIN_PASSWORD}" \
-d "grant_type=password"
You get a JSON response with the admin's token. Extract the value of property access_token from that response. Let us save it in the variable $ACCESS_TOKEN for later reference.
To create the user in your realm $REALM_NAME and get back its id execute:
URL="https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/"
curl --include -X -s POST "${URL}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "$USER_JSON" | grep "Location: ${URL}" | grep -o '[^/]\+$'
the flag --include will make curl include the headers, and the command grep "Location: ${URL}" will extract the location and the command grep -o '[^/]\+$' the user ID from that location.

How do I use my gitlab personal access token in my jelastic jps manifests?

Until now, I have always been working with public repositories, where everything is smooth and easy. However, I would like to now switch to private repos.
I saw this answer related to github repos. Unfortunately, it seems like it doesn't work the same for gitlab. In particular, the ?access_token=${settings.accessToken} does not seem to be recognized well by gitlab.
How should I proceed with my gitlab access token? What I was able to figure out until now (but I find this a little bit crap), is that I should replace
baseUrl: https://www.my-gitlab.com/my-company/my-project/my-repo/-/raw/master
onInstall:
- cmd:
- curl -fsSL ${baseUrl}/my-folder/my-script.sh | /bin/sh
- wget ${baseUrl}/my-folder/my-script.sh -O my-script.sh
with
globals:
GITLAB_API_URL: http://www.my-gitlab.com/api/v4/projects/my-project-id/repository/files
onInstall:
- cmd:
- curl -H "PRIVATE-TOKEN: ${settings.accessToken}" -fsSL ${globals.GITLAB_API_URL}/my-folder%2Fmy-script.sh/raw?ref=master | /bin/sh
- wget --header="PRIVATE-TOKEN: ${settings.accessToken}" ${globals.GITLAB_API_URL}/my-folder%2Fmy-script.sh/raw?ref=master -O my-script.sh
But I find the above replacement a bit complicated. I'm pretty sure there must be something equivalent to what is done with github on gitlab. Also, the above replacement does not quite work. For example, the call
curl -H "PRIVATE-TOKEN: ${settings.accessToken}" -fsSL ${globals.GITLAB_API_URL}/my-folder%2Fmy-script.sh/raw?ref=master | /bin/sh
with ${settings.accessToken} and ${globals.GITLAB_API_URL} replaced with the relevant values, works fine on my development PC; however, when that command runs on jelastic, I get the error
/bin/bash: line 1: {curl -H \"PRIVATE-TOKEN:<my-token>\" -fsSL http://www.my-gitlab.com/api/v4/projects/my-project-id/repository/files/my-folder/my-script.sh/raw?ref=master | /bin/sh}: No such file or directory","nodeid":63261,"exitStatus":127,"out":""}
I have no clue why that does not work and I guess using the gitlab api is not the right way to get my stuff done with curl and wget. Also, I have no clue how to get stuff like this working:
onInstall:
install:
jps: ${baseUrl}/jelastic/tools.jps?access_token=${settings.accessToken}
Can someone help?

How to fix conflicting source password error?

I'm trying to set up a gitlab CI/CD.
1 of the script I use is :
sshpass -p $PRIVATE_KEY ssh -p $PORT -o StrictHostKeyChecking=no $USER#$SERVER01 "cd /var/www/html/app && export HISTIGNORE='*sudo -S*' && echo "$PRIVATE_KEY" | ( sudo -S -k git fetch && sudo -S -k git pull )"
as you can see I'm trying to update the application in my server.
FYI, I have already set up the variables in the gitlab CI/CD settings page.
But, when the job runs, it always returns this error message :
Conflicting password source
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
-f filename Take password to use from file
-d number Use number as file descriptor for getting password
-p password Provide password as argument (security unwise)
-e Password is passed as env-var "SSHPASS"
With no parameters - password will be taken from stdin
-P prompt Which string should sshpass search for to detect a password prompt
-v Be verbose about what you're doing
-h Show help (this screen)
-V Print version information
At most one of -f, -d, -p or -e should be used
I have already googled around, but found no clue.
Any clue would be much appreciated.
I finally found the solution.
So the above command worked for master branch, but it didn't work for develop, knowing this pattern, I checked the variables settings, then found out that I turned on the Protect variable flag, the flag says Export variable to pipelines running on protected branches and tags only.
Since develop is not a protected branch, I was thinking that the variable values were not passed into the pipeline.
So, I unchecked this flag for all variables and finally got it working.

automatic docker login within a bash script

How can I preseed my credentials to docker login command within a script ?
I'm using a bash script that basically automates the whole process of setting up my custom VMs etc, but when I need to login to docker within the script to pull the images, I get the following error:
Username: FATA[0000] inappropriate ioctl for device
The command I was using is the following:
( echo "xxx"; echo "yyy"; echo "zzz" ) | docker login docker.somesite.org
Is this possible to achieve without using and coping over an existing .dockercfg file and how,
Many thanks.
Docker 18 and beyond
There's now an officially-documented way to do this:
cat ~/my_password.txt | docker login --username foo --password-stdin
Docker 1.11 through Docker 17
You can pass all the arguments on the command-line:
docker login --username=$DOCKER_USER --password=$DOCKER_PASS $DOCKER_HOST
If you don't specify DOCKER_HOST, you'll get the main Docker repo. If you leave out any of the arguments, you'll be prompted for that argument.
Older than 1.11
The same path as just above, except that you need to also pass an --email flag. The contents of this are not actually checked, so anything is fine:
docker login --username=$DOCKER_USER --password=$DOCKER_PASS $DOCKER_HOST --email whale#docker.com
To run the docker login command non-interactively, you can set the --password-stdin flag to provide a password through STDIN. Using STDIN prevents the password from ending up in the shell’s history, or log-files.
$ echo $DOCKER_PASS | docker login -u$DOCKER_USER --password-stdin $DOCKER_HOST
When you login to your private registry, docker auto create a file $HOME/.docker/config.json The file had the Credentials info, so you could save the file and copy to any host when you want to login the registry.
The file content like this:
{
"auths": {
"example.com": {
"auth": "xxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
Add-on If you want to login multi docker registry on one server ,just add another auth info.like this:
{
"auths": {
"example.com": {
"auth": "xxxxxxxxxxxxxxxxxxxxxxx"
},
"example1.com":{
"auth": "xxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
Now you can push and pull images from the example.com and example1.com.
For any random passer by that may stumble into this looking for a way to use this against an Openshift environment's container registry (Docker) you can use the following to provide the registry URI along with the credentials to log into it using an Openshift token.
$ echo "$(oc whoami -t)" | docker login -u $USER --password-stdin \
$(oc get route docker-registry -n default --no-headers | awk '{print $2}')
Login Succeeded
The above does 3 things:
Passes token retrieved from Openshift oc whoami -t
Determines Openshift's registry URI
$(oc get route docker-registry -n default --no-headers | awk '{print $2}'`)
Logs into registry using $USER + token from above
I was having massive issues with this, just wanted to add that the environment variable DOCKER_HOST has special meaning to docker to define the daemon socket it connects to, causing it to fail login. There's a full list of the environment variables docker uses here: https://docs.docker.com/engine/reference/commandline/cli/
I changed my environment variables to something else, e.g. REG_ and it worked
docker login --username $REG_USERNAME --password $REG_PASSWORD $REG_HOST
Note, if you're doing this in a gitlab runner, there's no need to use the --password-stdin flag if you're already using variable masking (you can, there's just no need).

openam - create a user with ssoadm

I have new goal. Be able to create users of openam with ssoadm.
I have read the documentation of Openam
https://wikis.forgerock.org/confluence/display/openam/ssoadm-identity#ssoadm-identity-create-identity
However, I don't know how to create a user and then assign it a password. For now I just can create users by openam web, but is not desirable, I want to automatize.
Somebody know how can I create a normal user with ssoadm?
./ssoadm create-identity ?
./ssoadm create-agent ?
UPDATE: I have continued with my investigation :) I think I'm closer than before
$ ./ssoadm create-identity -u amadmin -f /tmp/pwd.txt -e / -i Test -t User
Minimum password length is 8.
But where is the parameter for password?
Thanks!
To create a new user in the configured data stores you could execute the following ssoadm command:
$ openam/bin/ssoadm create-identity -e / -i helloworld -t User -u amadmin -f .pass -a givenName=Hello sn=World userPassword=changeit
Here you can see that I've defined the password as the userPassword attribute, which is data store dependent really. For my local OpenDJ this is perfectly legal, but if you are using a database or something else, then you'll have to adjust the command accordingly.
If you don't want to provide the attributes on the command line, then you could put all the values into a properties file, for example:
$ echo "givenName=Hello
sn=World
userPassword=changeit" > hello.txt
$ openam/bin/ssoadm create-identity -e / -i helloworld -t User -u amadmin -f .pass -D hello.txt
But I must say that using OpenAM for identity management is not recommended, you should use your data store's own tools to manage identities (i.e. use an LDAP client within your app, or just simply use the ldap* CLI tools). You may find that OpenAM doesn't handle all the different identity management related tasks as normally people would expect, so to prevent surprises use something else for identity management.

Resources