Acerca de la preparación del código para el análisis
Nota: En este artículo se describen las características disponibles con el paquete CodeQL CLI 2.12.7 que se incluye en la versión inicial de GitHub Enterprise Server 3.9.
Si el administrador del sitio ha actualizado tu versión de la CodeQL CLI a una versión más reciente, consulta la versión de GitHub Enterprise Cloud de este artículo para obtener información sobre las características más recientes.
Antes de analizar el código con CodeQL, debes crear una base de datos de CodeQL que contenga todos los datos necesarios para ejecutar consultas en el código. También puedes crear bases de datos de CodeQL por tu cuenta mediante la CodeQL CLI.
El análisis de CodeQL se basa en la extracción de datos relacionales del código y su uso para crear una base de datos de CodeQL. Las bases de datos de CodeQL contienen toda la información importante sobre un código base, que se puede analizar ejecutando consultas de CodeQL en él.
Antes de generar una base de datos de CodeQL, debes hacer lo siguiente:
- Instalar y configurar la CodeQL CLI. Para obtener más información, vea «Configuración de la CLI de CodeQL».
- Extraiga del repositorio el código que quiera analizar:
- En el caso de una rama, extraiga del repositorio el inicio de la rama que quiera analizar.
- Para una solicitud de incorporación de cambios, compruebe la confirmación del encabezado de la solicitud o una confirmación de combinación generada por GitHub de esa solicitud.
- Configure el entorno para el código base y asegúrese de que las dependencias estén disponibles.
- Para obtener los mejores resultados con lenguajes compilados, busque el comando build, si existe, para el código base. Normalmente está disponible en un archivo de configuración en el sistema de CI.
Una vez que el código base esté listo, puedes ejecutar codeql database create
para crear la base de datos. Para obtener más información, consulta "Creación de bases de datos para lenguajes no compilados" y "Creación de bases de datos para lenguajes compilados".
En ejecución codeql database create
Las bases de datos de CodeQL se crean ejecutando el comando siguiente desde la raíz de restauración del proyecto:
codeql database create <database> --language=<language-identifier>
Debe especificar:
-
<database>
: una ruta de acceso a la base de datos nueva que se va a crear. Este directorio se creará al ejecutar el comando; no se puede especificar un directorio existente. -
--language
: el identificador del lenguaje para el que se va a crear una base de datos. Cuando se usa con--db-cluster
, la opción acepta una lista separada por comas o se puede especificar más de una vez. CodeQL admite la creación de bases de datos para los lenguajes siguientes:Lenguaje Identificador C/C++ cpp
C# csharp
Go go
Java/Kotlin java
JavaScript/TypeScript javascript
Python python
Ruby ruby
Nota: El análisis de CodeQL para Kotlin se encuentra actualmente en versión beta. Durante la versión beta, el análisis del código de Kotlin y la documentación complementaria no serán tan exhaustivos como para otros lenguajes.
Si el código base tiene un comando de compilación o un script que invoca el proceso de compilación, se recomienda especificarlo también:
codeql database create <database> --command <build> \
--language=<language-identifier>
Opciones para crear bases de datos
Puedes especificar opciones adicionales en función de la ubicación del archivo de origen, si se tiene que compilar el código y si quieres crear bases de datos de CodeQL para más de un lenguaje.
Opción | Obligatorio | Uso |
---|---|---|
<database> | Especifica el nombre y ubicación de un directorio a crear para la base de datos de CodeQL. Se producirá un error en el comando si intenta sobrescribir un directorio existente. Si también especifica --db-cluster , este es el directorio primario y se crea un subdirectorio para cada lenguaje analizado. | |
--language | Especifica el identificador del lenguaje con el que se va a crear una base de datos, entre los siguientes: cpp , csharp , go , java , javascript , python , y ruby (usa javascript para analizar el código de TypeScript y java para analizar el código de Kotlin). Cuando se usa con --db-cluster , la opción acepta una lista separada por comas o se puede especificar más de una vez. | |
--command | Opción recomendada. Se usa para especificar el comando de compilación o el script que invoca el proceso de compilación para el código base. Los comandos se ejecutan desde la carpeta actual o, donde se define, desde --source-root . No es necesario para el análisis de Python y JavaScript o TypeScript. | |
--db-cluster | Se usa en códigos base de varios lenguajes para generar una base de datos para cada lenguaje especificado por --language . | |
--no-run-unnecessary-builds | Opción recomendada. Utilízalo para suprimir el comando de compilación para los lenguajes en donde el CodeQL CLI no necesite monitorear la compilación (por ejemplo, Python y JavaScript/TypeScript). | |
--source-root | Se usa si ejecuta la CLI fuera de la raíz de extracción del repositorio. De manera predeterminada, el comando database create supone que el directorio actual es el directorio raíz de los archivos de origen. Use esta opción para especificar otra ubicación. | |
--codescanning-config | Avanzado. Úsalo si tienes un archivo de configuración que especifica cómo crear las bases de datos CodeQL y qué consultas ejecutar en pasos posteriores. Para obtener más información, vea «Personalización de la configuración avanzada para el examen de código» y «database create». |
Puedes especificar opciones de extractor para personalizar el comportamiento de los extractores que crean bases de datos de CodeQL. Para obtener más información, vea «Opciones de extractor».
Para obtener información detallada sobre todas las opciones que se pueden usar al crear bases de datos, consulta "database create".
Ejemplo de un solo lenguaje
En este ejemplo se crea una única base de datos de CodeQL para el repositorio extraído en /checkouts/example-repo
. Usa el extractor de JavaScript para crear una representación jerárquica del código JavaScript y TypeScript en el repositorio. La base de datos resultante se almacena en /codeql-dbs/example-repo
.
$ codeql database create /codeql-dbs/example-repo --language=javascript \
--source-root /checkouts/example-repo
> Initializing database at /codeql-dbs/example-repo.
> Running command [/codeql-home/codeql/javascript/tools/autobuild.cmd]
in /checkouts/example-repo.
> [build-stdout] Single-threaded extraction.
> [build-stdout] Extracting
...
> Finalizing database at /codeql-dbs/example-repo.
> Successfully created database at /codeql-dbs/example-repo.
Ejemplo de lenguaje múltiple
En este ejemplo se crean dos base de datos de CodeQL para el repositorio extraído en /checkouts/example-repo-multi
. Usa:
--db-cluster
para solicitar el análisis de más de un lenguaje.--language
para especificar los lenguajes para los que se crearán las bases de datos.--command
para indicarle a la herramienta el comando de compilación para el código base, en este casomake
.--no-run-unnecessary-builds
para indicarle a la herramienta que omita el comando de compilación para los lenguajes en los que no es necesario (como Python).
Las bases de datos resultantes se almacenan en los subdirectorios python
y cpp
de /codeql-dbs/example-repo-multi
.
$ codeql database create /codeql-dbs/example-repo-multi \
--db-cluster --language python,cpp \
--command make --no-run-unnecessary-builds \
--source-root /checkouts/example-repo-multi
Initializing databases at /codeql-dbs/example-repo-multi.
Running build command: [make]
[build-stdout] Calling python3 /codeql-bundle/codeql/python/tools/get_venv_lib.py
[build-stdout] Calling python3 -S /codeql-bundle/codeql/python/tools/python_tracer.py -v -z all -c /codeql-dbs/example-repo-multi/python/working/trap_cache -p ERROR: 'pip' not installed.
[build-stdout] /usr/local/lib/python3.6/dist-packages -R /checkouts/example-repo-multi
[build-stdout] [INFO] Python version 3.6.9
[build-stdout] [INFO] Python extractor version 5.16
[build-stdout] [INFO] [2] Extracted file /checkouts/example-repo-multi/hello.py in 5ms
[build-stdout] [INFO] Processed 1 modules in 0.15s
[build-stdout] <output from calling 'make' to build the C/C++ code>
Finalizing databases at /codeql-dbs/example-repo-multi.
Successfully created databases at /codeql-dbs/example-repo-multi.
$
Progreso y resultados
Los errores se notifican si hay algún problema con las opciones especificadas. En el caso de los lenguajes interpretados y al especificar --build-mode none
para Java, el progreso de la extracción se muestra en la consola. Para cada archivo de origen, la consola muestra si la extracción se realizó correctamente o si se produjo un error. En el caso de los lenguajes compilados, la consola mostrará la salida del sistema de compilación.
Cuando la base de datos se crea correctamente, encontrarás un directorio nuevo en la ruta de acceso especificada en el comando. Si usaste la opción --db-cluster
para crear más de una base de datos, se crea un subdirectorio para cada lenguaje. Cada directorio de base de datos de CodeQL contiene varios subdirectorios, incluidos los datos relacionales (necesarios para el análisis) y un archivo de origen (una copia de los archivos de origen realizada en el momento en que se creó la base de datos), que se usa para mostrar los resultados del análisis.
Creación de bases de datos para lenguajes no compilados
La CodeQL CLI incluye extractores a fin de crear bases de datos para lenguajes no compilados, en concreto JavaScript (y TypeScript), Python y Ruby. Estos extractores se invocan automáticamente al especificar JavaScript, Python o Ruby como la opción --language
al ejecutar database create
. Al crear bases de datos para estos lenguajes, debes asegurarte de que todas las dependencias adicionales están disponibles.
Nota: Al ejecutar database create
para JavaScript, TypeScript, Python y Ruby, no debes especificar una opción --command
. De lo contrario, invalidará la invocación de extractor normal, que creará una base de datos vacía. Si creas bases de datos para varios lenguajes y uno de ellos es un lenguaje compilado, usa la opción --no-run-unnecessary-builds
a fin de omitir el comando de los lenguajes que no sea necesario compilar.
JavaScript y TypeScript
La creación de bases de datos para JavaScript no requiere dependencias adicionales, pero si el proyecto incluye archivos TypeScript, debes instalar Node.js 14 o una versión posterior que debe estar disponible en PATH
como node
. En la línea de comandos, puedes especificar --language=javascript
para extraer archivos JavaScript y TypeScript:
codeql database create --language=javascript --source-root <folder-to-extract> <output-folder>/javascript-database
Aquí hemos especificado una ruta de acceso --source-root
, que es la ubicación donde se ejecuta la creación de la base de datos, pero no es necesariamente la raíz de restauración del código base.
De manera predeterminada, los archivos de los directorios node_modules
y bower_components
no se extraen.
Python
Al crear bases de datos para Python, debes asegurarte de lo siguiente:
- Tener Python 3 instalado y disponible para el extractor de CodeQL.
- Tener instalada la versión de Python que usa el código.
- Tener acceso al sistema de administración de empaquetado pip y poder instalar los paquetes de los que depende el código base.
- Tener instalado el módulo virtualenv de pip.
En la línea de comandos, debes especificar --language=python
. Por ejemplo:
codeql database create --language=python <output-folder>/python-database
Esto ejecuta el subcomando database create
desde la raíz de restauración del código, lo que genera una base de datos de Python nueva en <output-folder>/python-database
.
Ruby
La creación de bases de datos para Ruby no requiere dependencias adicionales. En la línea de comandos, debes especificar --language=ruby
. Por ejemplo:
codeql database create --language=ruby --source-root <folder-to-extract> <output-folder>/ruby-database
Aquí hemos especificado una ruta de acceso --source-root
, que es la ubicación donde se ejecuta la creación de la base de datos, pero no es necesariamente la raíz de restauración del código base.
Creación de bases de datos para lenguajes compilados
En el caso de los lenguajes compilados, CodeQL debe invocar el sistema de compilación necesario a fin de generar una base de datos, por lo que el método de compilación debe estar disponible para la CLI. Este enfoque crea bases de datos que incluyen código generado. CodeQL tiene dos métodos para compilar código base:
- "Detección automática de compilaciones (autobuild)"
- "Comandos de compilación especificados por el usuario
Detección automática del sistema de compilación
El CodeQL CLI incluye los constructores automáticos para el código C/C++, C#, Go, and Java. Los generadores automáticos de CodeQL permiten compilar proyectos para lenguajes compilados sin especificar ningún comando de compilación. Cuando se invoca un generador automático, CodeQL examina el origen en busca de evidencias de un sistema de compilación e intenta ejecutar un conjunto óptimo de comandos necesarios para extraer una base de datos. Para obtener más información, vea «Análisis de código de CodeQL para lenguajes compilados».
Un generador automático se invoca automáticamente cuando se ejecuta codeql database create
para un lenguaje compilado si no incluye una opción --command
. Por ejemplo, para un código base en C#, puede ejecutar simplemente:
codeql database create --language=csharp <output-folder>/csharp-database
Si un código base usa un sistema de compilación estándar, basarse en un generador automático suele ser la manera más sencilla de crear una base de datos. En el caso de los orígenes que requieren pasos de compilación que no son estándar, es posible que tengas que definir de forma explícita cada paso en la línea de comandos.
Notas:
- Si vas a compilar una base de datos de Go, instala la cadena de herramientas de Go (versión 1.11 o una posterior) y, si hay dependencias, el administrador de dependencias adecuado (por ejemplo, dep).
- El generador automático de Go intenta detectar automáticamente el código escrito en Go en un repositorio y solo ejecuta scripts de compilación en un intento de capturar dependencias. Para forzar que CodeQL limite la extracción a los archivos que ha compilado el script de compilación, establece la variable de entorno
CODEQL_EXTRACTOR_GO_BUILD_TRACING=on
o usa la opción--command
a fin de especificar un comando de compilación.
Especificación de comandos de compilación
Los ejemplos siguientes están pensados para darte una idea de algunos de los comandos de compilación que puedes especificar para los lenguajes compilados.
Nota: La opción --command
acepta un único argumento; si necesitas usar más de un comando, especifica --command
varias veces. Si necesitas pasar subcomandos y opciones, el argumento entero debe ir entre comillas para que se interprete correctamente.
-
Proyecto de C/C++ compilado con
make
:codeql database create cpp-database --language=cpp --command=make
-
Proyecto de C# compilado con
dotnet build
:Es recomendable agregar
/t:rebuild
para asegurarse de que se compilará todo el código, o bien realizar un elementodotnet clean
anterior (el código que no esté compilado no se incluirá en la base de datos de CodeQL):codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild'
-
Ve al proyecto compilado con la variable de entorno
CODEQL_EXTRACTOR_GO_BUILD_TRACING=on
:CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
-
Ve al proyecto compilado con un script de compilación personalizado:
codeql database create go-database --language=go --command='./scripts/build.sh'
-
Proyecto de Java compilado con Gradle:
# Use `--no-daemon` because a build delegated to an existing daemon cannot be detected by CodeQL. # To ensure isolated builds without caching, add `--no-build-cache` on persistent machines. codeql database create java-database --language=java --command='gradle --no-daemon clean test'
-
Proyecto de Java compilado con Maven:
codeql database create java-database --language=java --command='mvn clean install'
-
Proyecto de Java compilado con Ant:
codeql database create java-database --language=java --command='ant -f build.xml'
-
Proyecto compilado con Bazel:
# Navigate to the Bazel workspace. # Before building, remove cached objects # and stop all running Bazel server processes. bazel clean --expunge # Build using the following Bazel flags, to help CodeQL detect the build: # `--spawn_strategy=local`: build locally, instead of using a distributed build # `--nouse_action_cache`: turn off build caching, which might prevent recompilation of source code # `--noremote_accept_cached`, `--noremote_upload_local_results`: avoid using a remote cache codeql database create new-database --language=<language> \ --command='bazel build --spawn_strategy=local --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results //path/to/package:target' # After building, stop all running Bazel server processes. # This ensures future build commands start in a clean Bazel server process # without CodeQL attached. bazel shutdown
-
Proyecto compilado con un script de compilación personalizado:
codeql database create new-database --language=<language> --command='./scripts/build.sh'
Este comando ejecuta un script personalizado que contiene todos los comandos necesarios para compilar el proyecto.
Uso del seguimiento indirecto de la compilación
Si los generadores automáticos de la CodeQL CLI para lenguajes compilados no funcionan con el flujo de trabajo de CI y no puedes encapsular invocaciones de comandos de compilación con codeql database trace-command
, puedes usar el seguimiento indirecto de la compilación para crear una base de datos de CodeQL. A fin de usar el seguimiento indirecto de la compilación, el sistema de CI debe poder establecer variables de entorno personalizadas para cada acción de compilación.
Para crear una base de datos de CodeQL con seguimiento indirecto de la compilación, ejecuta el comando siguiente desde la raíz de desprotección del proyecto:
codeql database init ... --begin-tracing <database>
Debe especificar:
<database>
: una ruta de acceso a la base de datos nueva que se va a crear. Este directorio se creará al ejecutar el comando; no se puede especificar un directorio existente.--begin-tracing
: crea scripts que se pueden usar para configurar un entorno en el que se realizará un seguimiento de los comandos de compilación.
Puedes especificar otras opciones para el comando codeql database init
con normalidad.
Nota: Si la compilación se ejecuta en Windows, debes establecer --trace-process-level <number>
o --trace-process-name <parent process name>
a fin de que la opción apunte a un proceso de CI primario que observará todos los pasos de compilación para el código que se va a analizar.
El comando codeql database init
dará generará un mensaje:
Created skeleton <database>. This in-progress database is ready to be populated by an extractor. In order to initialise tracing, some environment variables need to be set in the shell your build will run in. A number of scripts to do this have been created in <database>/temp/tracingEnvironment. Please run one of these scripts before invoking your build command.
Based on your operating system, we recommend you run: ...
El comando codeql database init
crea <database>/temp/tracingEnvironment
con archivos que contienen variables de entorno y valores que permitirán que CodeQL realice un seguimiento de una secuencia de pasos de compilación. Estos archivos se denominan start-tracing.{json,sh,bat,ps1}
. Usa uno de estos archivos con el mecanismo del sistema de CI a fin de establecer variables de entorno para pasos futuros. Puede:
- Leer el archivo JSON, procesarlo e imprimir variables de entorno en el formato que espera el sistema de CI. Por ejemplo, Azure DevOps espera
echo "##vso[task.setvariable variable=NAME]VALUE"
. - O bien, si el sistema de CI conserva el entorno, obtén el script de
start-tracing
adecuado para establecer las variables de CodeQL en el entorno de shell del sistema de CI.
Compila el código; opcionalmente, anula las variables de entorno mediante un script de end-tracing.{json,sh,bat,ps1}
del directorio donde se almacenan los scripts de start-tracing
; y, después, ejecuta el comando codeql database finalize <database>
.
Una vez que hayas creado una base de datos de CodeQL mediante el seguimiento indirecto de la compilación, puedes trabajar con ella como con cualquier otra base de datos de CodeQL. Por ejemplo, analiza la base de datos y carga los resultados en GitHub si usas el examen de código.
Ejemplo de creación de una base de datos de CodeQL mediante el seguimiento indirecto de la compilación
Nota: Si usas canalizaciones de Azure DevOps, la manera más sencilla de crear una base de datos de CodeQL es usar GitHub Advanced Security for Azure DevOps. Para obtener documentación, consulta Configuración de GitHub Advanced Security for Azure DevOps en Microsoft Learn.
En el ejemplo siguiente se muestra cómo puedes usar el seguimiento indirecto de la compilación en una canalización de Azure DevOps para crear una base de datos de CodeQL:
steps:
# Download the CodeQL CLI and query packs...
# Check out the repository ...
# Run any pre-build tasks, for example, restore NuGet dependencies...
# Initialize the CodeQL database.
# In this example, the CodeQL CLI has been downloaded and placed on the PATH.
- task: CmdLine@1
displayName: Initialize CodeQL database
inputs:
# Assumes the source code is checked out to the current working directory.
# Creates a database at `<current working directory>/db`.
# Running on Windows, so specifies a trace process level.
script: "codeql database init --language csharp --trace-process-name Agent.Worker.exe --source-root . --begin-tracing db"
# Read the generated environment variables and values,
# and set them so they are available for subsequent commands
# in the build pipeline. This is done in PowerShell in this example.
- task: PowerShell@1
displayName: Set CodeQL environment variables
inputs:
targetType: inline
script: >
$json = Get-Content $(System.DefaultWorkingDirectory)/db/temp/tracingEnvironment/start-tracing.json | ConvertFrom-Json
$json.PSObject.Properties | ForEach-Object {
$template = "##vso[task.setvariable variable="
$template += $_.Name
$template += "]"
$template += $_.Value
echo "$template"
}
# Execute the pre-defined build step. Note the `msbuildArgs` variable.
- task: VSBuild@1
inputs:
solution: '**/*.sln'
msbuildArgs: /p:OutDir=$(Build.ArtifactStagingDirectory)
platform: Any CPU
configuration: Release
# Execute a clean build, in order to remove any existing build artifacts prior to the build.
clean: True
displayName: Visual Studio Build
# Read and set the generated environment variables to end build tracing. This is done in PowerShell in this example.
- task: PowerShell@1
displayName: Clear CodeQL environment variables
inputs:
targetType: inline
script: >
$json = Get-Content $(System.DefaultWorkingDirectory)/db/temp/tracingEnvironment/end-tracing.json | ConvertFrom-Json
$json.PSObject.Properties | ForEach-Object {
$template = "##vso[task.setvariable variable="
$template += $_.Name
$template += "]"
$template += $_.Value
echo "$template"
}
- task: CmdLine@2
displayName: Finalize CodeQL database
inputs:
script: 'codeql database finalize db'
# Other tasks go here, for example:
# `codeql database analyze`
# then `codeql github upload-results` ...
Pasos siguientes
- Para obtener información sobre cómo usar la CodeQL CLI para analizar la base de datos que creaste a partir del código, consulta «Análisis del código con consultas de CodeQL».