Sobre a criação de conjuntos de consultas do CodeQL
Note
Este artigo descreve os recursos disponíveis com o pacote CodeQL CLI 2.16.5 incluído na versão inicial de GitHub Enterprise Server 3.13.
Se o administrador do site atualizou a versão do CodeQL CLI para uma mais recente, confira a versão GitHub Enterprise Cloud deste artigo para obter informações sobre os recursos mais recentes.
Os conjuntos de consultas do CodeQL oferecem uma forma de selecionar consultas, com base no nome de arquivo, no local no disco, em um pacote CodeQL ou em propriedades de metadados. Crie conjuntos com as consultas que você deseja usar mais nas análises do CodeQL.
Os conjuntos de consultas permitem que você passe várias consultas ao CodeQL sem precisar especificar o caminho para cada arquivo de consulta individualmente. As definições do pacote de consultas são armazenadas em arquivos YAML com a extensão .qls
. Uma definição de pacote é uma sequência de instruções, em que cada instrução é um mapeamento YAML com (geralmente) uma única chave. As instruções são executadas na ordem em que aparecem na definição do pacote de consultas. Depois que todas as instruções na definição do conjunto tiverem sido executadas, o resultado será um pacote de consultas selecionadas.
Note
As consultas personalizadas que você deseja adicionar a um pacote de consultas precisam estar em um pacote do CodeQL e conter os metadados de consulta corretos. Para obter mais informações, confira Como usar consultas personalizadas com a CodeQL CLI.
Como localizar as consultas a serem adicionadas a um conjunto de consultas
Ao criar um conjunto de consultas, primeiro você precisa especificar os locais das consultas que deseja selecionar. Você pode definir o local de uma ou mais consultas usando:
-
Uma instrução
query
: instrui o CodeQL a procurar um ou mais arquivos especificados.ql
:- query: <path-to-query>
O argumento precisa ser um ou mais caminhos de arquivo, em relação ao pacote do CodeQL que contém a definição do conjunto.
-
Uma instrução
queries
: solicita que o CodeQL verifique recursivamente um diretório em busca de arquivos.ql
:- queries: <path-to-subdirectory>
O caminho do diretório precisa ser relativo à raiz do pacote do CodeQL que contém o arquivo de definição do conjunto. Para localizar as consultas relativas a um pacote do CodeQL diferente, adicione um campo
from
:- queries: <path-to-subdirectory> from: <ql-pack-name> version: ^x.y.z
O campo
version
é opcional e especifica um intervalo de versões compatíveis deste pacote do CodeQL. Se você não especificar uma versão, será usada a mais recente do pacote. -
Uma instrução
qlpack
: solicita que o CodeQL resolva consultas no conjunto padrão do pacote do CodeQL nomeado:- qlpack: <qlpack-name> version: ^x.y.z
O conjunto padrão de um pacote de consultas inclui um conjunto recomendado de consultas dentro desse pacote de consultas. Nem todos os pacotes de consultas têm um conjunto padrão. Se o pacote de consultas especificado não definir um conjunto padrão, a instrução qlpack será resolvida para todas as consultas dentro do pacote.
O campo
version
é opcional e especifica um intervalo de versões compatíveis deste pacote do CodeQL. Se você não especificar uma versão, será usada a mais recente do pacote.
Note
Quando os nomes de caminho aparecem nas definições do conjunto de consultas, eles sempre precisam conter uma barra /
como separador de diretório. Isso garante que as definições do conjunto de consultas funcionem em todos os sistemas operacionais.
Você precisa adicionar pelo menos uma instrução query
, queries
ou qlpack
à definição do conjunto. Caso contrário, nenhuma consulta será selecionada. Se o conjunto não contiver mais instruções, todas as consultas encontradas na lista de arquivos, no diretório especificado ou no pacote do CodeQL nomeado serão selecionadas. Se houver mais instruções de filtragem, somente as consultas que correspondem às restrições impostas por essas instruções serão selecionadas.
Como filtrar as consultas em um conjunto de consultas
Depois de definir o grupo inicial de consultas a serem adicionadas ao conjunto especificando as instruções query
, queries
ou qlpack
, você pode adicionar as instruções include
e exclude
. Estas instruções definem os critérios de seleção com base em propriedades específicas:
- Quando você executa uma instrução
include
em um conjunto de consultas, todas as consultas que correspondem às condições são mantidas na seleção e as que não correspondem são removidas. - Quando você executa uma instrução
exclude
em um conjunto de consultas, todas as consultas que correspondem às condições são removidas da seleção e as que não correspondem são mantidas.
A ordem das instruções de filtro é importante. A primeira instrução de filtro exibida após as instruções de localização determina se as consultas são incluídas ou excluídas por padrão. Se o primeiro filtro for um include
, as consultas localizadas inicialmente só farão parte do conjunto se corresponderem a um filtro explícito include
. Se o primeiro filtro for um exclude
, as consultas localizadas inicialmente farão parte do conjunto, a menos que sejam excluídas explicitamente.
As instruções subsequentes são executadas em ordem e as instruções que aparecem posteriormente no arquivo têm precedência sobre as instruções anteriores. Portanto, as instruções include
poderão ser substituídas por instruções exclude
posteriores que correspondam à mesma consulta. Da mesma forma, exclude
s podem ser substituídas por uma include
posterior.
Para as duas instruções, o argumento é um bloco de restrição, ou seja, um mapa YAML que representa as restrições. Cada restrição é uma entrada de mapa, em que a chave normalmente é uma propriedade de metadados de consulta. O valor pode ser:
- Uma só cadeia de caracteres.
- Uma expressão regular entre
/
. - Uma lista que contém cadeias de caracteres e/ou expressões regulares.
Para corresponder a uma restrição, um valor de metadados precisa corresponder a uma das cadeias de caracteres ou expressões regulares. Quando há mais de uma chave de metadados, cada chave precisa ser correspondida.
As chaves de metadados padrão disponíveis para correspondência são: description
, id
, kind
, name
, tags
, precision
e problem.severity
.
Para obter mais informações sobre as propriedades de metadados de consulta, confira Metadados para consultas do CodeQL.
Além das marcas de metadados, as chaves no bloco de restrição também podem ser:
query filename
: corresponde ao último componente de caminho do nome do arquivo de consulta.query path
: corresponde ao caminho para o arquivo de consulta em relação ao pacote do CodeQL que ele contém.tags contain
: uma das cadeias de caracteres de correspondência fornecidas precisa corresponder a um dos componentes separados por espaço do valor da propriedade de metadados@tags
.tags contain all
: cada uma das cadeias de caracteres de correspondência fornecidas precisa corresponder a um dos componentes da propriedade de metadados@tags
.
Exemplos de filtragem das consultas que serão executadas
Um caso de uso comum é criar um conjunto de consultas que execute todas as consultas em um pacote do CodeQL, exceto algumas consultas específicas que o usuário não deseja executar. Em geral, recomendamos a filtragem na id
da consulta, que é um identificador exclusivo e estável de cada consulta. As três definições de conjunto de consultas a seguir são semanticamente idênticas e filtram pela consulta id
:
Esse filtro corresponde a todas as consultas no conjunto padrão de codeql/cpp-queries
, exceto às duas consultas com os identificadores excluídos:
- qlpack: codeql/cpp-queries
- exclude:
id:
- cpp/cleartext-transmission
- cpp/cleartext-storage-file
Neste exemplo, uma instrução exclude
separada é usada para cada consulta:
- qlpack: codeql/cpp-queries
- exclude:
id: cpp/cleartext-transmission
- exclude:
id: cpp/cleartext-storage-file
Neste exemplo, uma expressão regular exclui as mesmas duas consultas. Ela também excluiria todas as consultas futuras adicionadas ao conjunto com identificadores que começam com: cpp/cleartext-
:
- qlpack: codeql/cpp-queries
- exclude:
id:
- /^cpp\/cleartext-.*/
Para definir um conjunto que selecione todas as consultas no conjunto padrão do pacote codeql/cpp-queries
do CodeQL e depois refine-as para incluir apenas consultas de segurança, use:
- qlpack: codeql/cpp-queries
- include:
tags contain: security
Para definir um conjunto que seleciona todas as consultas com @kind problem
e @precision high
no diretório my-custom-queries
, use:
- queries: my-custom-queries
- include:
kind: problem
precision: very-high
Observe que a definição do conjunto de consultas a seguir se comporta de maneira diferente da definição acima. Essa definição seleciona as consultas que são @kind problem
ou @precision very-high
:
- queries: my-custom-queries
- include:
kind: problem
- include:
precision: very-high
Para criar um conjunto que selecione todas as consultas com @kind problem
no diretório my-custom-queries
, exceto aquelas com @problem.severity recommendation
, use:
- queries: my-custom-queries
- include:
kind: problem
- exclude:
problem.severity: recommendation
Para criar um conjunto que selecione todas as consultas com @tag security
e @precision high
ou very-high
no pacote codeql/cpp-queries
do CodeQL, use:
- queries: .
from: codeql/cpp-queries
- include:
tags contain: security
precision:
- high
- very-high
Note
Você pode usar o comando codeql resolve queries /path/to/suite.qls
para ver quais consultas são selecionadas por uma definição de conjunto de consultas. Para saber mais, confira resolve queries.
Como reutilizar definições de conjunto de consultas existentes
As definições de conjunto de consultas existentes podem ser reutilizadas especificando:
-
Uma instrução
import
: adiciona as consultas selecionadas por um arquivo.qls
já definido ao conjunto atual:- import: <path-to-query-suite>
O caminho para o conjunto importado precisa ser relativo ao pacote do CodeQL que contém a definição do conjunto atual. Se o conjunto de consultas importado estiver em um pacote do QL diferente, use:
- import: <path-to-query-suite> from: <ql-pack> version: ^x.y.z
O campo
version
é opcional e especifica um intervalo de versões compatíveis deste pacote do CodeQL. Se você não especificar uma versão, será usada a mais recente do pacote.As consultas adicionadas usando uma instrução
import
podem ser filtradas usando as instruções subsequentesexclude
. -
Uma instrução
apply
: adiciona todas as instruções de um arquivo.qls
já definido ao conjunto atual. As instruções no arquivo.qls
aplicado são executadas como se aparecessem no lugar deapply
. As instruçõesinclude
eexclude
do conjunto aplicado também atuam em consultas adicionadas por instruções anteriores:- apply: <path-to-query-suite>
A instrução
apply
também pode ser usada para aplicar um conjunto de condições reutilizáveis, salvas em um arquivo.yml
, a várias definições de consulta. Veja os exemplos abaixo para obter mais informações.
Exemplos de reutilização
Para usar as mesmas condições em várias definições de conjunto de consultas, crie um arquivo .yml
separado contendo as instruções. Por exemplo, salve o seguinte em um arquivo chamado reusable-instructions.yml
:
- include:
kind:
- problem
- path-problem
tags contain: security
precision:
- high
- very-high
Adicione reusable-instructions.yml
ao mesmo pacote do CodeQL que o conjunto de consultas atual. Depois, em um ou mais conjuntos de consultas, use a instrução apply
para aplicar as instruções reutilizáveis ao conjunto atual. Por exemplo:
- queries: queries/cpp/custom
- apply: reusable-instructions.yml
Isso filtrará as consultas em queries/cpp/custom
para incluir apenas aquelas que correspondem às condições reutilizáveis.
Você também pode criar uma definição de conjunto usando reusable-instructions.yml
em consultas em um pacote do CodeQL diferente. Se o arquivo .qls
estiver no mesmo pacote do CodeQL que as consultas, você poderá adicionar um campo from
logo após a instrução apply
:
# load queries from the default suite of my-org/my-other-custom-queries
- qlpack: my-org/my-other-custom-queries
# apply the reusable instructions from the my-org/my-custom-instructions CodeQL pack
- apply: reusable-instructions.yml
from: my-org/my-custom-instructions
version: ^1.2.3 # optional
Um caso de uso comum de uma instrução import
é aplicar um filtro adicional a consultas de outro conjunto de consultas. Por exemplo, esse conjunto filtrará ainda mais o conjunto cpp-security-and-quality
e excluirá as consultas de precisão low
e medium
:
- import: codeql-suites/cpp-security-and-quality.qls
from: codeql/cpp-queries
- exclude:
precision:
- low
- medium
Se você quiser executar include
nas consultas importadas de outro pacote, a sintaxe será um pouco diferente:
- import: codeql-suites/cpp-security-and-quality.qls
from: codeql/cpp-queries
- exclude: {}
- include:
precision:
- very-high
- high
Observe a instrução vazia exclude
. Isso é necessário para garantir que a próxima instrução include
consiga filtrar as consultas do conjunto importado.
Nomeando um conjunto de consultas
Você pode dar um nome para o conjunto de consultas especificando uma instrução description
:
- description: <name-of-query-suite>
Como salvar um conjunto de consultas
Salve o conjunto de consultas em um arquivo com uma extensão .qls
e adicione-o a um pacote do CodeQL. Para saber mais, confira Como personalizar a análise com pacotes CodeQL.
Usando conjuntos de consultas com CodeQL
Você pode especificar conjuntos de consultas na linha de comando para qualquer comando que aceite arquivos .qls
. Por exemplo, você pode compilar as consultas selecionadas por uma definição de conjunto usando query compile
ou usar as consultas em uma análise usando database analyze
. Para obter mais informações sobre como analisar bancos de dados do CodeQL, confira Como analisar o código com as consultas CodeQL.