Gitlab has a built-in integration with Vault but that requires a Premium/Ultimate paid license.

If you want to pull multiple secrets from Vault and pass them to other jobs within the pipeline for free, this is what I came up with.

Vault Configuration

# enable auth endpoint
vault auth enable jwt
# create policy granting access to desired secrets
vault policy write gitlab - <<EOF
path "kv/data/gitlab" {
  capabilities = ["list", "read"]
}
EOF
# create role linking to policy
vault write auth/jwt/role/gitlab - <<EOF
{
  "role_type": "jwt",
  "policies": ["gitlab"],
  "user_claim": "user_email",
  "bound_audiences": ["https://gitlab.example.com"],
  "bound_claims_type": "string",
  "bound_claims": {
    "iss": [
      "gitlab.example.com",
      "https://gitlab.example.com"
    ],
    "project_path": [
      "my_group/project1",
      "my_group/project2"
    ]
  }
}
EOF
# configure the auth method
vault write auth/jwt/config \
  jwks_url="https://gitlab.example.com/oauth/discovery/keys"

Gitlab Pipeline

# .gitlab-ci.yml
read-secrets:
  stage: .pre
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://gitlab.example.com
  variables:
    VAULT_ADDR: https://vault.example.com
    VAULT_JWT_ROLE: gitlab
    VAULT_SECRETS: |
      secret_one:
        path: kv/gitlab
        field: first_field
      secret_two:
        path: kv/gitlab
        field: second_field
  image: hashicorp/vault:1.17
  
  script:
    - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=$VAULT_JWT_ROLE jwt=$VAULT_ID_TOKEN)"
    - test -n "$VAULT_TOKEN" # ensure we got a token
    - apk add --no-cache yq
    - echo "$VAULT_SECRETS" | yq e 'to_entries | .[] | .key as $key | .value 
      | "vault kv get -format=json -field=\(.field) \(.path) | sed '\''s/^\"//; s/\"$//'\'' 
      | xargs -I {} echo \"\($key)={}\"" ' > retrieve_secrets.sh
    - chmod +x retrieve_secrets.sh
    - ./retrieve_secrets.sh > secrets.env
    
  artifacts:
    reports:
      dotenv: secrets.env
    access: 'none' # don't let anyone download artifacts
    expire_in: 1 day # accomodate long-running pipelines
 
display-secrets:
  script:
    - echo "First secret is $secret_one"
    - echo "Second secret is $secret_two"

Refs: