Как настроить Jira для помощи отделу helpdesk при выходе или увольнении сотрудника

Kate

Administrator
Команда форума
В данной статье мы решили поделиться одним из вариантов автоматизации процессов, необходимых для приема на работу или увольнения сотрудника. Особо полезна эта статья для PM, HR и непосредственно тех ребят, которые подготавливают рабочие места. Лично мое мнение — данную статью должен прочитать каждый, кто хочет минимизировать рутину в своей компании, ведь текучка персонала в той или иной степени есть везде.

Привет! Я Юра Ложкин, Atlassian Engineer в OS.ECO. Я занимался реализацией, тестированием и внедрением данного проекта в компании, и теперь делюсь этим опытом с вами.

Жизненный цикл задачи​

В самом начале стоит сказать, что проект работает в связке Jira + Jenkins + Gitlab CI.

Мы назвали этот проект «Сотрудники». У него есть всего один тип задачи — «Новый сотрудник». У этой задачи две основные функции:

  1. Создавать пользователя в ERP (база данных по учету ресурсов предприятия).
  2. Генерировать и блокировать доступы на корпоративные ресурсы.
image_31087207181643293255924.png


Раскрываем все карты​

«Заведение» сотрудника на ресурсы компании

При создании задачи на вывод сотрудника нужно указать:

  1. Персональную информацию о новом сотруднике (ФИО, дату рождения, дату выхода).
  2. Доступы, которые необходимы для выполнения рабочих обязанностей.
  3. Домен компании, куда выходит сотрудник (для создания почты пользователя).
  4. Указываем должность, компанию, отдел и т.д.
  5. Указываем руководителя сотрудника и HR.
Также есть возможность добавить наблюдателя и комментарий при необходимости.

image_72955114101643293255935.png


image_30399745421643293255889.png


На изображении выше идет проверка ФИО. В полях First Name и Last Name идет проверка того, указаны ли данные на латинице. А в поле ФИО — данные должны быть указаны на кириллице (и тут тоже идет проверка).

image_53045958991643293255929.png


Выше изображена задача после ее создания.

Далее нам нужно создать пользователя в ERP, нажав на переход (ERP acc) в задаче. После успешной отработки скрипта, ERP возвращает Username — уникальное имя пользователя, которого больше нет в ERP, и employee_id — айди пользователя, используемый для блокировки учетной записи в будущем.

image_15677115441643293255908.png


Вторым шагом создаем доступы для данного пользователя, нажав на переход (Enroll access) в задаче. Запускается джоба в Jenkins, которая и создает доступы на ресурсах компании, добавляет соответствующие права и создает почту (к примеру, на G Suite). На этом же этапе генерируется VPN-сертификат для пользователя и создается учетка в Duo. После этого пользователю на почту приходит письмо с доступами на корп. ресурсы.

image_27437457871643293255919.png


Админу, который инициировал создание доступов, приходит сообщение в слак. Также в задаче будет добавлен скрытый комментарий с доступами:

image_98094781161643293255916.png


Если же на данном этапе выполнения задачи что-то пошло не так, бот отправит сообщение в слак админу, который инициировал создание доступов:
User not created
See logs here
jenkins/job/generate_access/111

В целом, на этом работа хелпдеска заканчивается, и задача двигается дальше по воркфлоу.

Сотрудник в штате — статус Staff — и со всеми необходимыми доступами:

image_45522324451643293255909.png


Автоматическая генерация дополнительного VPN-сертификата на ПК или телефон​

Когда сотрудник уже в штате, мы можем сгенерировать дополнительный VPN-сертификат прямо из задачи в Jira. В чем плюс данной генерации сертификата — сотруднику хелпдеск не обязательно иметь ssh доступ на сервер VPN. После нажатия на переход (Approval to generate VPN) сотрудник хелпдеска выбирает VPN-сервер и устройство, дальше задача переходит на руководителя. После согласования руководителем запускается джоба в Jenkins по генерации VPN. После успешной генерации сертификата бот добавит комментарий к задаче с данными VPN.

Увольнение сотрудника​

Когда сотрудник увольняется, открываем задачу по его выводу и нажимаем на переход (Dismissal), заполняем поле Lastday (последний рабочий день).

Поле Lastday необходимо для блокировки учетной записи в ERP. После перехода задачи в статус (Dismissal), который означает увольнение сотрудника, идет проверка учетки по всем ресурсам компании. Добавляется комментарий к задаче со списком ресурсов, которые проверялись.

image_2301375631643293255902.png


Далее нажимаем на переход (Revoke Access). Запускается джоба, блокирующая все доступы сотрудника, которые были найдены. После успешной отработки в слак приходит сообщение со списком ресурсов, на которых была заблокирована учетная запись. И такое же сообщение добавляется в задаче в Jira в виде скрытого комментария.

Далее задача идет по воркфлоу, и в итоге попадает в статус Done — это говорит о том, что сотрудник уволен, доступы отозваны и техника принята.

Важно! Все комментарии к задаче добавляются скрытыми, их видит только сотрудник helpdesk.

Техническая реализация проекта​

На переходах создания и блокирования учетной записи в ERP в Post Functions используется скрипт, написанный на SIL (Simple Issue Language), в котором передаются параметры в ERP и делается вызов API.

На переходах генерации/проверки/отзыва доступов в Post Functions используется скрипт, написанный на SIL (Simple Issue Language), в котором передаются параметры в Jenkins и делается вызов API.

Ниже описан pipeline в Jenkins, в котором идет генерация доступов:

pipeline {
agent any
environment {
JIRA_USER = credentials('jira-user')
REFRESH_TOKEN = credentials('refresh_token')
duo_ik = credentials('duo_integration_key')
duo_sk = credentials('duo_secret_key')
duo_ah = credentials('duo_api_hostname')

}
options { timestamps() }
stages {

// создание учетной записи в IPA
stage('Create user account to LDAP') {
steps {
script {
if (env.ldap.toBoolean()) {
sh "bash ./create_access/ldaps/ipa.sh --uid ${uid} --first ${first} --last ${last} --domain ${domain} --pass ${env.pass}"
LDAP = "ipa01 password: ${env.pass}"
} else {
LDAP = "not used"
}
}
}
}

// создание почты
stage('Create mail account') {
steps {
script {
if (env.mail.toBoolean()) {
token = sh(script: 'curl -i -X POST https://www.googleapis.com/oauth2/v4/token -H "Content-Type: application/json" --data-binary "@${REFRESH_TOKEN}" | grep access_token | sed \'s/ \"access_token\": \"//\' | sed \'s/\",//\'', returnStdout: true).trim()
user = sh(returnStatus: true, script: """curl -H "Authorization: Bearer ${token}" -X POST -d \'{"primaryEmail": "${uid}@{domain}", "name": {"givenName": "${first}", "familyName": "${last}"}, "suspended": false, "password": "${env.pass}", "changePasswordAtNextLogin": true, "ipWhitelisted": false, "emails": [{"address": "${uid}@{domain}", "primary": true } ], "orgUnitPath": "/", "includeInGlobalAddressList": true }\' -H "Content-Type: application/json" -i https://www.googleapis.com/admin/directory/v1/users""")
MAIL = "Gsuite OS ECO"
} else {
MAIL = "not used"
}
}
}
}

// генерация сертификата впн
stage('Generate VPN certificate') {
steps {
script {
if (env.ldap.toBoolean() && env.mail.toBoolean() && env.vpn.toBoolean()) {
sh "ssh -o StrictHostKeyChecking=no -l jenkins vpn_server sudo python /opt/nice_vpn/manager/ldapcache.py"
sh "ssh -o StrictHostKeyChecking=no -l jenkins vpn_server sudo python /opt/nice_vpn/manager/cert-manager.py generate --login ${env.uid}"
show_cert = sh (returnStdout: true, script: "ssh -o StrictHostKeyChecking=no -l jenkins vpn_server sudo python /opt/nice_vpn/manager/cert-manager.py show-certs --login ${env.uid} | sed -n 4p | sed 's/|//g'")
vpn_ip = show_cert.split()[3]
vpn_cn = show_cert.split().last()
VPN = "vpn_server *ip*: ${vpn_ip} *CN*: ${vpn_cn}"
} else {
VPN = "not used"
}
}
}
}

// создание учетной записи в DUO
stage('Enroll duo mobile user') {
steps {
script {
if (env.ldap.toBoolean() && env.mail.toBoolean() && env.vpn.toBoolean()) {
fullname = first + ' ' + last
duo_user = sh(script: "python create_access/duo_create_user.py 'POST' ${env.duo_ah} '/admin/v1/users' 'username=${vpn_cn}&email=${env.uid}@${domain}&realname=${fullname}' ${env.duo_sk} ${env.duo_ik} 'XXXXXXXXXXXXXXXXXXX'", returnStdout: true).trim()
DUO = "OS ECO"
} else {
DUO = "not used"
}
}
}
}

// отправляет комментарий с доступами в задачу в джире
stage('Jira callback') {
steps {
script {
sh "curl -D- -H \"Authorization: Basic ${env.JIRA_USER}\" -X POST --data '{\"body\": \"Accesses created: \\n *LDAP* - ${LDAP} \\n *MAIL* - ${MAIL} \\n *VPN* - ${VPN} \\n *DUO* - ${DUO} \\n \", \"visibility\": {\"type\": \"role\",\"value\": \"Service Desk Team\"}}' -H \"Content-Type: application/json\" https://jira.os.eco/rest/api/2/issue/${issue}/comment"
}
}
}

}

post {
success {
script {
// отправляет сотруднику письмо с доступами
emailext body: '''${SCRIPT, template="notification.groovy"}''',
subject: 'Access ${project} | ${first} ${last}',
to: '${uid}@${domain}'
}
}
failure {
slackSend (
// в случае фейла, отправляет сообщение админу в слак
color: "danger",
channel: "@${env.admin}",
message: "*User not created* \n *See logs here* \n ${env.BUILD_URL}",
tokenCredentialId: "slack_bot"
)
}
}

}

Вместо выводов​

Сколько же времени теперь занимает вывод/увольнение сотрудника?

Ранее на выдачу доступов тратилось около 20-30 минут, сейчас же — 2 минуты, что невероятно круто! Теперь сотрудники хелпдеск делают меньше рутинной работы, уменьшается риск человеческого фактора (где-то доступ не выдал, где-то разные логины и т.д.). При увольнении сотрудника идет проверка наличия его учетной записи на всех ресурсах компании, и если учетка есть, то она автоматически блокируется. Ситуация, когда «забыли забрать доступы», сводится к нулю.

 
Сверху