Como criar campos dinâmicos com Script Fields no Jira Server

Se você curte o Jira, não deixe de conferir meu artigo sobre gestão de backlog usando Jira!

No último artigo eu ensinei como criar diversos tipos de automações em Jira. Venho trabalhando com esta ferramenta desde 2018 e ela é bem poderosa, mais até do que a que usei por mais de 10 anos, o famoso TFS da Microsoft.

Entre as inúmeras funcionalidades, o Jira permite criar diversos campos customizados de vários tipos, mas, além disso, campos que carregam o seu conteúdo dinamicamente a partir de scripts Groovy, graças ao plugin Adaptavist ScriptRunner. Vou mostrar aqui como criar um campo dinâmico.

Este tutorial foi feito usando o Jira na versão server/on-premise (v7.10), mas possivelmente deve funcionar em versões posteriores e talvez até na cloud, desde que tenha o plugin/add-on do Script Runner. Você precisa de permissões de administrador do Jira para conseguir fazer o que vou mostrar.

Este artigo não tem a pretensão de ensinar a administrar Jira, mas apenas a dar um upgrade nas suas skills se já for um administrador de Jira Server. Para quem quer aprender a administrar Jira, recomendo os serviços de consultoria da e-core, parceiros Atlassian no Brasil e com quem eu aprendi.

Custom Fields

Por padrão o Jira permite que você crie Custom Fields ou Campos Personalizados. Nada mais são do que inputs comuns, usando os tipos pré-existentes do Jira, mas como rótulos/labels personalizados e que adicionam mais informações às screens já existentes ou a novas screens.

Caso isso seja novidade para você, o passo-a-passo abaixo mostra como criar um custom field simples. Me perdoe as imagens em português, foi uma imagem que tirou os prints e ela usa o Jira em pt-br (eu prefiro usar em inglês pois facilita a procura por informações na Internet).

  1. Acesse o painel de administração;
  2. Seção Issues;
  3. Sub-seção Fields;
  4. Opção Custom Fields/Add Custom Field
Add Custom Field
Add Custom Field

Na tela que se abrirá, preencha de acordo com o campo que precisa (campo de texto, de seleção, etc). Cada tipo de campo possui as suas particuliaridades, como a Select List, que exige que tu preencha manualmente todas as opções do drop-down.

A seguir, depois de clicar em Create, você vai ser solicitado que selecione em quais telas este campo vai aparecer.

Telas do campo
Telas do campo

E pronto. Caso ele ainda não apareça nas telas que você selecionou, dê uma olhada na Screen para ver se não tem de torná-lo visível pois às vezes ele está na tela, mas oculto/hidden.

Mas e para criar custom fields baseados em scripts, como faz?

Livro para Agile Coaches

Script Fields

Você pode criar campos dinâmicos que carregam o seu conteúdo a partir de scripts, o que chamamos de Script Field. Esse recurso é muito poderoso para, por exemplo:

  • exibir informações de linked issues dentro das issues principais (e vice-versa);
  • exibir informações resultantes de cálculos ou transformações de outros dados da issue;

Uma vez com o campo criado, é possível adicioná-lo em qualquer screen ou até mesmo usá-lo em queries e reports.

Para criar um Script Field você deve:

  1. Entre em Administration;
  2. Escolha a opção Issues;
  3. Clique em Custom Fields, abaixo da seção Fields;
  4. Clique em Add Custom Field;
  5. Em Select Field Type, encontre Scripted Field dentro de Advanced (o ícone é o mesmo do Script Runner);
  6. Next;
  7. Dê um nome e uma descrição ao campo (este último é opcional) e salve;
  8. Selecione todas as telas em que este campo deve aparecer e clique em Update;
  9. Retorna a Administration, Add-ons, Script Runner e Fields;
  10. Encontre o seu Scripted Field criado e depois clique em Edit;
Script Field
Script Field

Preencha o formulário como segue:

  • Field Name: não editável;
  • Field Description: não editável;
  • Note: uma nota opcional;
  • Template: como esse campo será renderizado na screen;
  • Script: o código Groovy que vai retornar o conteúdo desse campo. É aqui que a magia acontece e esse código sempre recebe um objeto issue como argumento, com as propriedades da issue atualmente visível na screen onde esse script field está.
  • Preview Issue Key: coloque o id de uma issue aqui e clique no botão preview para ver como seu Script Field vais e parecer na screen.

Clique em Update para finalizar.

Caso seu script field não aparece na screen que deveria, reveja as configurações de screen do custom field e/ou verifique na screen se o campo está aparecendo no editor visual dela.

Um exemplo de código Groovy para script field é mostrado abaixo. Nele, nós ascendemos na hierarquia da issue atual até encontrar qual o Projeto (um issue type custom) ela pertence, imprimindo essa informação então no custom script field:

No exemplo abaixo, de outro script field, dado um issue do tipo Mudança, a gente busca o item originador desta mudança (outra issue) e se tiver mais de um, pega apenas o primeiro para exibir no custom script field:

E nesse último abaixo, mais simples de todos, temos um custom script field que apenas exibe o nome do épico associado a esta issue:

Espero ter ajudado!

Infelizmente eu não possuo um curso de Jira, mas caso se interesse por métodos ágeis em geral, dê uma conferida no meu curso online de Scrum e Métodos Ágeis clicando no banner abaixo.

Curso de Scrum e Métodos Ágeis

Como criar automações e scripts no Jira Server

Se você curte o Jira, não deixe de conferir meu artigo sobre gestão de backlog usando Jira!

O Jira permite criar diversos tipos de automações, principalmente através de plugins como o famoso Adaptavist ScriptRunner ou o Automation for Jira. Vou mostrar aqui como criar alguns tipos diferentes de automação, todas usando o Jira Server v7.10 (a versão que mais tive contato, mas é possível que funcione nas posteriores) e necessitando de permissão de administrador para serem criadas.

Como uma dica geral, todas automações que exigem script Groovy você pode usar log.warn(“mensagem”) para registrar logs e ajudar no seu debug enquanto estiver programando e quando estiver em produção e ter de fazer troubleshooting.

Este artigo não tem a pretensão de ensinar a administrar Jira, mas apenas a dar um upgrade nas suas skills se já for um administrador de Jira Server. Para quem quer aprender a administrar Jira, recomendo os serviços de consultoria da e-core, parceiros Atlassian no Brasil e com quem eu aprendi.

Tipo 1: Automações de Workflow

Você pode criar automações que serão disparadas quando uma issue for realizar uma transição dentro do seu workflow, ou seja, mudar de um estado para outro. Esse recurso é muito poderoso para:

  • criar validações na troca de estado, como garantir que campos estejam preenchidos, por exemplo;
  • Realizar atividades automáticas após uma troca de estado (atualizar um campo, disparar um script Groovy, etc);
  • Disparar eventos que podem ser tratados depois, pelo Jira (listeners, mais adiante);

Para criar uma validação de campo obrigatório (ou que tenha de ter um valor específico preenchido), você deve:

  1. Clicar em Project Settings (ícone da engrenagem);
  2. Clicar em Workflows;
  3. Clicar no botão de Edit do workflow em questão (ícone do lápis);
  4. Seleciona a visualização em forma de Diagram;
  5. Clica na linha da transição que deseja adicionar a validação;
  6. Seleciona a opção Validators (ou Post Function se for querer disparar eventos depois da transição);
  7. Clique no link “Add validator”;
  8. Seleciona a opção “Script validator [Script Runner]”;
  9. Seleciona a opção “Simple scripted validator”;
Automação por Workflow
Automação por Workflow

A seguir, preencha os campos da seguinte forma:

  • Note: nome da validação;
  • Condition: o seu código Groovy que deve retornar true ou false, dizendo se aquela transição vai poder acontecer ou não;
  • Error Message: mensagem de erro que vai aparecer se a validação bloquear a transição (retorno false);
  • Field: se você deixar esse campo em branco, a mensagem de erro vai aparecer no topo do formulário. Preencha se quiser que ela apareça ao lado do campo;

No exemplo abaixo, o campo Área de Negócio deve ser preenchido para que uma issue possa ser criada:

Caso você quer que algo aconteça DEPOIS da transição ocorrer, você usa post-function ao invés de validator e além de vários templates prontos, você também pode codificar o comportamento usando Script Runner.

Tipo 2: Automações para Jira Service Desk

Você pode criar automações baseadas no Service Desk e seus serviços. Para fazê-lo, precisa de permissão de administrador no Jira Service Desk ao invés do Jira Software. Esse recurso é muito poderoso para:

  • Criar alertas diversos, como SLA expirando, por exemplo;
  • Atualizar issues relacionadas toda vez que a principal for alterada;
  • Reabrir issues que tenham sido comentadas;
  • Muitos tipos de regras personalizadas;
  1. Clique em Project Settings;
  2. Clique em Automation;
  3. Clique em Add Rule;
  4. Selecione o tipo de regra que deseja adicionar, neste exemplo usarei Custom Rule (Regra Personalizada);
Automação de Jira Service Desk
Automação de Jira Service Desk

Preencha os campos como segue:

  • Rule name: o nome da automação;
  • Description: a descrição do que faz esta automação;

Construa a automação como segue:

  • When: a situação ou evento que irá disparar esta automação. Adicione tantas triggers (gatilhos) quanto forem necessárias. Por exemplo, toda vez que o status de uma issue seja atualizado.
  • If: a condição (uma ou mais) que será validada para esta automação executar ou não. As condições disponíveis no if dependem do when. Quando for uma issue, por exemplo, as condições vão ser relacionadas a issues.
  • Then: uma ou mais ações que serão executadas quando esta automação ocorrer. Por exemplo, você pode mudar o estado de uma issue ou enviar um e-mail.

Neste tipo de automação não qualquer criação de script, é tudo visual.

Tipo 3: Automações com Escalation Services

Você pode criar automações que serão disparadas automaticamente, de tempos em tempos. Esse também é um recurso do ScriptRunner e permite fazer coisas como fechar chamados automaticamente depois de X tempo;

Para criar um escalation service, você deve:

  1. Ir na administração geral do Jira Software estando autenticado como administrador;
  2. Acesse a aba Add-ons;
  3. No menu esquerdo, vá em Escalation Services, dentro da subseção Script Runner;
  4. Clique em Create Escalation Service;

Existem vários tipos, vamos usar aqui o Escalation Service de Issue.

Escalation Services
Escalation Services

Preencha os campos do formulário como segue:

  • Description: o nome do escalation service;
  • JQL Query: a consulta que irã ser executada de tempos em tempos para executar a ação automática sobre as issues retornadas;
  • As User: o usuário que irá executar a automação;
  • Interval/CRON Expression: uma expressão CRON que determine a periodicidade da automação;
  • Action: opcional, permite escolher uma transição de workflow pré-existente, útil se você apenas quer mudar o status das issues retornadas pelo JQL;
  • Additional issue actions: script Groovy que faz a operação que você deseja, nas issues retornadas pelo JQL.
  • Transition Options: alguns cheats para tornar a transição mais fácil como ignorar validators, permissões ou conditions.

Clique em Add e o tempo começará a correr, executando a automação no próximo CRON. Caso queira executar imediatamente, clique em “Run now”.

Livro para Agile Coaches

Tipo 4: Automações com Listeners

Você pode criar automações que serão disparadas automaticamente, quando algum evento acontecer no Jira. Esse também é um recurso do ScriptRunner e permite fazer coisas parecidas com as post-functions de workflow. Na verdade, a base dos Listeners são “escutar” (listen) eventos gerados por transições de estado, mas diferente das automações de workflow, você não cria em um workflow, mas de maneira global e genérica, o que é muito útil quando tem vários times com diferentes workflows mas uma automação e aplica a todos eles.

Para criar um listener, você deve:

  1. Acesse Administration;
  2. Add-ons;
  3. Clique na opção Listeners, dentro da subseção ScriptRunner;
  4. Clique em Create Listener;
  5. Escolha um dos templates prontos ou a opção Custom Listener para adicionar um código Groovy personalizado, opção que vou usar aqui;
Listener
Listener

Preencha o formulário como segue:

  • Note: o nome do listener;
  • Project(s): um ou mais projetos que este listener vai ficar escutando eventos;
  • Events: os eventos que vão disparar este listener. Você pode escolher eventos pré-definidos do Jira (que ele dispara sozinho) ou algum evento que você tenha criado manualmente e que dispare através de workflow post-functions ou de outras formas existentes;
  • Inline script: seu código Groovy. Ele recebe um objeto event por padrão, com as propriedades do evento;
  • Script file: opcional, permite dizer o caminho de um arquivo com o código Groovy dentro.

Clique em Add.

Um exemplo de código Groovy para listener pode ser visto abaixo. Neste exemplo, quando uma issue é resolvida (evento Issue Resolved) e ela está associada a um épico, ela propaga a sua informação de épico às issues de Service Desk (SDN) relacionadas à ela:

Tipo 5: Automações com e-mail

Você pode criar automações de e-mails que serão disparadas automaticamente, de tempos em tempos, baseada em consultas construídas por você (JQL). Esse é um recurso natural do Jira Software, embora com o Jira Service Desk também possa ser feito, como mencionado anteriormente.

  1. Faça uma consulta qualquer (JQL) na caixa de pesquisa do Jira;
  2. Salve a sua consulta, dando um nome à ela;
  3. Clique em Details e selecione a opção New Subscription;
Filter Subscription
Filter Subscription

Configure a Subscription dessa forma:

  • Recipients: quem vai receber essa assinatura de e-mails? Você pode enviar para grupos de pessoas;
  • Schedule: qual a recorrência? Em Advanced você pode definir uma expressão CRON para a recorrência;
  • “E-mail this filter…”: por padrão o resultado da consulta só é enviado por e-mail quando ele traz resultados. Marque se quiser receber um e-mail mesmo sem resultados na consulta.

Ao clicar em Subscribe, a automação de emails passará a funcionar.

Espero ter ajudado!

Infelizmente eu não possuo um curso de Jira, mas caso se interesse por métodos ágeis em geral, dê uma conferida no meu curso online de Scrum e Métodos Ágeis clicando no banner abaixo.

Curso de Scrum e Métodos Ágeis

Autenticação JSON Web Token (JWT) em Node.js – Parte 2

Atualizado em 10/02/2020 para facilitar o entendimento.

JSON Web Token, o famoso JWT, é de longe a forma mais comum de segurança utilizada em web APIs RESTful depois do uso de SSL/TLS. Quando temos variados clientes consumindo nossas APIs, saber quem está autenticado ou não, ou ainda, que tem autorização ou não para fazer as chamadas, é importantíssimo.

Na primeira parte deste tutorial eu ensinei como implantar um mecanismo de JWT em uma API Node.js, adicionando esta importante camada de segurança. Dentre as dúvidas mais comuns acerca desta técnica está a segurança do token, afinal ele é o ponto mais exposto na técnica e sequestro de tokens é a forma mais comum de tentar burlar este mecanismo.

Claro que usando SSL (sugiro Lets Encrypt que é gratuito) esse risco de captura diminui consideravelmente uma vez que a conexão está criptografada e encorajo fortemente você a não aceitar requisições usando HTTP. No entanto, sabemos que para tudo existem brechas a serem exploradas principalmente por parte de pessoas maliciosas dentro da sua própria empresa muitas vezes…

O risco do JWT

Mas o token não é criptografado? Eu olhei ele e vi um monte de letras e números aleatórios…

Não, o token apenas é codificado em base64, uma representação textual de um conjunto de bytes, se você jogá-lo em qualquer decodificador online, verá as três partes que o compõem sendo que a única ilegível é a terceira onde temos a assinatura digital do servidor, atestando que aquele token foi gerado corretamente pelo seu servidor, o que impede que tokens fake se passem por tokens reais.

No entanto, para essa assinatura é necessário um segredo/secret. Esse segredo é usado tanto para assinar quanto para verificar a assinatura (e autenticidade) de um token. Se você tem apenas uma webapi que usa o JWT, isso é bem tranquilo. Agora, se você possui diferentes microservices e todos eles precisam de autenticação/autorização via JWT, então você tem um problema pois:

  • ou você faz com que o cliente se autentique em cada um dos microservices que vai usar;
  • ou você compartilha o secret entre todos eles.;

Uma solução possível para este problema é usar um API Gateway na frente de todos microserviços. Daí todos eles confiariam no gateway, sem ficar pedindo ou verificando tokens. Mas geralmente bons APIs gateways custam caro, embora dê pra fazer um mais caseiro.

Antes de eu entrar em uma possível solução barata para mitigar esse risco, vale lembrar que é importante você ter uma maneira fácil e rápida de invalidar tokens em caso de fraude de chamadas, para que a área de segurança possa agir rapidamente nestas situações. Falarei mais sobre isso no futuro.

Mas voltando ao assunto central: como podemos adicionar mais segurança em nosso JWT?

Entendendo o JWT

Para entendermos realmente o JWT na prática, primeiro compartilho abaixo uma pequena API que implementa este mecanismo, para que você possa acompanhar meu raciocínio sem precisar refazer todo tutorial anterior.

Para fazer funcionar este código, você terá de instalar os seguintes pacotes com o comando abaixo:

Se você rodar este projeto simples ele deve funcionar como esperado: a rota clientes só pode ser acessada com um JWT válido. Para obter um, POST na rota de login com usuário e senha corretos no corpo.

Se pegarmos o token abaixo…

E jogarmos em um decodificador de base64 online teremos…

A primeira parte é o header, a segunda é o payload e a terceira é a assinatura do servidor (um hash criado usando o header + payload + secret configurado no servidor). A assinatura é que realmente garante que este token não é forjado, mas para que ela possa ser verificada, a API deve conhecer o mesmo secret usado na assinatura. E isso é um problema de segurança, afinal, se você tem uma senha que muita gente conhece, ela não é uma senha segura…

Mas como podemos garantir que este token possa ser usado em diferentes microservices sem compartilhar o secret com todos eles?

Assinatura assimétrica do JWT

Como estou falando de um token que navega entre diferentes microservices por meio inseguro (internet) o ideal é uma criptografia assimétrica, onde o emissor/servidor irá gerar o token assinado com a chave privada (de posse somente dele) e os consumidores/clientes podem verificá-lo usando a chave pública (de posse de todos microservices).

Assim, todos microservices confiam na emissão de tokens a partir um servidor central, enquanto podem validar sua assinatura para garantir que não foi forjado, sem saber o secret original.

Primeiro, vamos criar um par de chaves (uma pública e outra privada) usando o algoritmo RSA, um dos mais famosos e seguros do mundo de tipo assimétrico. O jeito mais fácil de gerar um par para fins de estudo é usando um gerador online, como esse aqui. O Format Scheme é PKCS #1 e o tamanho da chave varia de 256 bits a 2048 e embora chaves maiores sejam mais seguras (cada vez que você dobra o tamanho multiplica por 6x a dificuldade de quebra da chave) atente ao fato de que seu JWT deverá ser decifrado pelo servidor a cada requisição e que chaves maiores são mais demoradas para decifrar, mesmo com a chave certa.

Como é apenas para estudo, fiz com o menor tamanho comercialmente aceito (1024, enquanto que 2048 é o mais recomendado até 2030) e minha chave pública ficou assim (salve em um arquivo public.key):

Enquanto que minha privada ficou assim (salve em um arquivo private.key):

Agora, em nossa API, vamos mudar levemente o nosso código que gera os tokens para que os mesmos sejam assinados de maneira assimétrica.

As alterações estão apenas a partir da linha que declaro a privateKey, que substitui o nosso secret padrão que estávamos usando. A leitura do arquivo da chave é feita usando módulo fs (adicione um require no topo do arquivo) e nas opções de assinatura (terceiro argumento da função) dizemos o algoritmo de hashing que o RSA vai usar no seu algoritmo interno (RS256 no meu caso represa SHA-256).

Atenção: caso o seu arquivo de chave secreta tenha senha (como são geralmente os .PEM gerados pelo OpenSSL, que é a ferramenta que recomendo que você use) você deve passar um objeto {key, passphrase} no segundo argumento do sign ao invés de apenas a privatekey.

Agora, ao se autenticar, o servidor lhe retornará um token com assinatura criptografada de forma assimétrica, o que permite que vários serviços possam verificar sua assinatura usando a chave pública, ao invés da chave privada, usada para assinar o token da primeira vez, o equivalente ao secret original.

Atenção: se você tiver o erro “digest too big for RSA key” quer dizer que sua chave é pequena demais para o texto a ser cifrado. Neste caso, use chaves maiores (eu não tive problema a partir de 1024-bit).

Verificando o JWT

Agora é hora de ajustar o código que verifica a assinatura do JWT. Enquanto que para criarmos a assinatura usamos a private key, para verificar a mesma usamos a public key.

Note que a alteração foi bem sutil mesmo: carregamos a public key a partir do respectivo arquivo, passamos ela pra função verify, bem como um objeto informando o algoritmo de hashing que usamos junto do RSA (RS256 refere-se a SHA-256). Sim, é um array de algoritmos e passei apenas um.

Agora, se você obter um token pela rota de login e usá-lo para acessar a rota de clientes, verá que está funcionando como deveria e que no uso comum de apenas um cliente e servidor, não mudou em nada. Mas se tiver que confiar neste token em diferentes microservices, todos eles podem verificar a assinatura usando a chave pública.

Note que esta abordagem consome mais recursos computacionais que os tokens comuns. Esteja preparado para um aumento custo de hardware e/ou do tempo entre cada requisição que necessita deste token.

Espero que tenha gostado do artigo!

Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu curso sobre programação web com Node.js!

Curso Node.js e MongoDB