GEKO Part 2: Gitlab + Elasticsearch + Kibana!

Intro: Why GEKO?

Maybe I should answer what is GEKO first… G = Gitlab, E = Elasticsearch, K =Kibana O = OpenCTI
What if your Gitlab repositories could do more than just host your detection rules.
What if it could validate, manage, update, revert, query and even more . Welcome to Detection as Code (DaC) – where Gitlab, Elasticsearch, and Kibana team up to not only host your detections, but change the way your rules are managed.
If you missed GEKO Part 1 follow the link, if not hello again.

Where we left off

We used the below docker-compose.yml to set up and run gitlab, by running docker-compose -d up gitlab in the same directory as the file. We retrieved the password from /etc/gitlab/initial_root_password and signed in.

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    container_name: es
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
      - xpack.security.enabled=true
      - ELASTIC_PASSWORD=Changeme
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - elastic

  kibana:
    image: docker.elastic.co/kibana/kibana:8.17.0
    container_name: kib
    volumes:
      - /home/lab/kibana.yml:/usr/share/kibana/config/kibana.yml
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - ELASTICSEARCH_SERVICEACCOUNTTOKEN=<run the following in elastic to get key> # sudo docker exec -it es ./bin/elasticsearch-service-tokens create elastic/kibana kibana (Run this in ES to generate a token)
      - xpack.encryptedSavedObjects.encryptionKey=abcdeabcdeabcdeabcdeabcdeabcdeab
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
    networks:
      - elastic

  gitlab:
    image: gitlab/gitlab-ce:latest
    container_name: gitlab
    hostname: gitlab.local
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://gitlab.local'
        gitlab_rails['gitlab_shell_ssh_port'] = 2224
    ports:
      - "80:80"
      - "443:443"
      - "2224:22"
    volumes:
      - gitlab_config:/etc/gitlab
      - gitlab_logs:/var/log/gitlab
      - gitlab_data:/var/opt/gitlab
    networks:
      - elastic

  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    container_name: gitlab-runner
    volumes:
      - './runner_config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'
    networks:
      - elastic
    restart: always

volumes:
  esdata:
    driver: local
  gitlab_config:
    driver: local
  gitlab_logs:
    driver: local
  gitlab_data:
    driver: local

networks:
  elastic:
    driver: bridge

Next Steps: Add a runner.

Using the docker-compose.yml above, all we need to do to start the runner is run docker-compose -d up gitlab-runner. This will align a runner to run our commands. But we need to let Gitlab know about the runner, and tell the runner what we want it to do.

Go to settings > CI/CD > Runners, as shown below.

Screenshot of GitLab CI/CD settings focusing on the Runners section, highlighting options for setting up and managing GitLab runners.

Clicking New project runner will take us to the screen below, ensure Run untagged jobs is checked. this will allow us to run jobs that believe it or not are untagged. We may want to tag jobs in the future to only run a python job if tagged with python for example.

Settings page for creating a new project runner in GitLab, including fields for tags, runner description, and configuration options.

Once we click Create runner Gitlab will instruct us what we need to do, although we’ll make a few adjustments as our runner is running in a docker instance.

Side quest: Docker

I said in Part 1 that I’d share some docker commands, so before we move on and run some commands here’s a few helpful things;
We’ve currently only run docker from a docker-compose.yml file, but we could just as easily run it as 1 command line; which would be cumbersome for persistence. If we wanted to start the runner from above instance the command would be docker run -d –name gitlab-runner –restart always –network elastic -v $(pwd)/runner_config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
You can see how this can grow, however we will need to run some of these going forward. So below should clarify some thing.

CommandDescription
docker –helpShows the options available, –help can be used through to give current options available.
-v or –volumeMap volumes or folders from your host to the docker container <local>:<container>.
execExecute commands in the running container.
-d or –detachRuns the container in the background (detached).
-i or –interactiveKeeps STDIN open, even if not attached, so we can interact with the container.
-t or –ttyAllocates a pseudo-TTY (i.e., creates a terminal session).
–networkAttach container to specific network, to allow them to communicate.
-p or –portsMaps host ports to container ports.

Connect the runner!

Now that we’ve familiarized ourselves with some commands, we can add the GitLab-runner. After clicking Create runner we get the register runner page.
* If this didn’t load, change the domain to the host IP of Gitlab, alternatively, add the IP to your host file.

Screenshot of the GitLab runner registration page, displaying options for operating systems, cloud platforms, and container environments, with instructions for creating a runner.

We need to run the command gitlab-runner register from our gitlab-runner container we can run the command from our host with docker exec -it gitlab-runner gitlab-runner register or docker exec -it gitlab-runner bash (giving us a shell to the Gitlab-runner) followed by gitlab-runner register. Either way we’ll be presented with a few questions.

Terminal output showing GitLab runner registration process with prompts for URL, registration token, runner name, and executor type.

I’ve provided my answers ‘http://gitlab.local&#8217;, my token that was generated by Gitlab, then a name, I’ve chosen ‘Linux’ then an executor. This will depend on your needs, but I’ve chosen ‘shell’. This means that any commands I give to the runner, the runner will run as shell commands. Once completed, you should see the You’ve registered a new runner. We can now use the runner.

Screenshot of the GitLab Runner registration page, displaying options for operating systems, cloud providers, and containers, with instructions for registering a new runner.

Conclusion

With GitLab and Gitlab-runner all talking nicely in Docker, and our GitLab Runner now registered and ready, we’ve officially laid the groundwork for Detection as Code.

🪜NEXT STEPS

We’ll get the runner running 🏃‍♂️, along with Elasticsearch and Kibana.
Remember: GEKO isn’t just a stack; it’s a mindset. By combining version control, pipeline automation, and search-driven visibility, you’re building a system that’s powerful, traceable, and scalable. Stay tuned, this is where GEKO really starts to fly. 🦎

Leave a Reply

Discover more from Planned Link

Subscribe now to keep reading and get access to the full archive.

Continue reading