使用Terraform更新服务原理密码

时间:2019-04-02 09:58:31

标签: azure terraform terraform-provider-azure

根据Terraform的到期时间更新服务准则密码

第一次使用密码设置服务原理非常正常,但是,我想使密码过期,如果密码即将过期,则会生成一个新密码并使用该密码更新服务原理,我不是完全确定如何在Terraform中执行条件操作,因为我对Terraform还是很陌生,文档并没有真正谈论仅在创建服务原理时更新服务原理,并且在此方法过期时没有数据对象可获取

到目前为止,我有这个(完全公开这是我正在帮助的更大的地形基础的一部分):

resource "azuread_application" "current" {
  name = "test"
}

resource "azuread_service_principal" "current" {
  application_id = "${azuread_application.current.application_id}"
}

resource "random_string" "password" {
  length  = 64
  special = true
}

resource "azuread_service_principal_password" "current" {
  service_principal_id = "${azuread_service_principal.current.id}"
  value                = "${random_string.password.result}"
  end_date_relative    = "2160h"   # valid for 90 days
}

由于该密码仅在90天内有效,因此我想在terraform到期之前运行terraform并更新密码

更新1:

似乎,如果确实更改了azuread_service_principal_password资源,则它视为依赖关系树中的更改,并重新创建附加了服务原理的资源,这意味着无法将状态保持在需要更新的Terraform中的服务原则凭据

更新2:

我尝试执行以下操作,但是它的缺点是每次运行terraform apply时都会运行:

terraform脚本:

resource "azuread_application" "current" {
  name = "${var.metadata_name}"
}

resource "azuread_service_principal" "current" {
  application_id = "${azuread_application.current.application_id}"
}
resource "random_string" "password" {
  length  = 64
  special = true
}

resource "azuread_service_principal_password" "current" {
  service_principal_id = "${azuread_service_principal.current.id}"
  value                = "${random_string.password.result}"
  end_date_relative    = "2160h"                                   # valid for 90 days
}


resource "null_resource" "password_updater" {
  # Updates everytime you run terraform apply so it will run this script everytime
  triggers {
    timestamp = "${timestamp()}"
  }

  provisioner "local-exec" {
    command = "sh ${path.module}/update_service_password.sh ${azuread_service_principal.current.id} ${var.resource_group} ${azurerm_kubernetes_cluster.current.name}"
  }
}

脚本:

#!/bin/sh
service_principle_id=$1
resource_group=$2
cluster_name=$3

# get service password expiration
expiration=$(az ad sp list --filter="objectId eq '$service_principle_id'" | jq '.[].passwordCredentials' | jq '.[].endDate' | cut -d'T' -f 1 | cut -d'"' -f 2)

# Format date for condition
now=$(date  +%Y%m%d%H%M%S)
expiration_date=$(date -d "$expiration - 30 days"  +%Y%m%d%H%M%S)


# Compare today with expiration date
if [ ${now} -ge ${expiration_date} ];
then
    # IF expiration date in the next 30 days rest password
    sp_id=$(az aks show -g ${resource_group} -n ${cluster_name} --query servicePrincipalProfile.clientId -o tsv)
    service_principle_secret=$(az ad sp credential reset --name ${sp_id} --end-date $(date -d "+ 90 days"  +%Y-%m-%d) --query password -o tsv)

    # Update cluster with new password
    az aks update-credentials \
    --resource-group ${resource_group} \
    --name ${cluster_name} \
    --reset-service-principal \
    --service-principal ${sp_id} \
    --client-secret ${service_principle_secret}
fi

3 个答案:

答案 0 :(得分:0)

对于服务主体,可以通过Azure CLI az ad sp reset重设其密码,但是您需要具有这样做的权限。

答案 1 :(得分:0)

我只是将其设置为“答案”,因为在与服务原理terraform模块的开发人员交谈后,他们告诉我,如果有更好的方法,请以其他方式不可能,请评论:

答案:

使用null_resource提供程序来运行运行更新的脚本-

resource "azuread_application" "current" {
  name = "${var.metadata_name}"
}

resource "azuread_service_principal" "current" {
  application_id = "${azuread_application.current.application_id}"
}
resource "random_string" "password" {
  length  = 64
  special = true
}

resource "azuread_service_principal_password" "current" {
  service_principal_id = "${azuread_service_principal.current.id}"
  value                = "${random_string.password.result}"
  end_date_relative    = "2160h"                                   # valid for 90 days
}


resource "null_resource" "password_updater" {
  # Updates everytime you run terraform apply so it will run this script everytime
  triggers {
    timestamp = "${timestamp()}"
  }

  provisioner "local-exec" {
    command = "sh ${path.module}/update_service_password.sh ${azuread_service_principal.current.id} ${var.resource_group} ${azurerm_kubernetes_cluster.current.name}"
  }
}

脚本:

#!/bin/sh
service_principle_id=$1
resource_group=$2
cluster_name=$3

# get service password expiration
expiration=$(az ad sp list --filter="objectId eq '$service_principle_id'" | jq '.[].passwordCredentials' | jq '.[].endDate' | cut -d'T' -f 1 | cut -d'"' -f 2)

# Format date for condition
now=$(date  +%Y%m%d%H%M%S)
expiration_date=$(date -d "$expiration - 30 days"  +%Y%m%d%H%M%S)


# Compare today with expiration date
if [ ${now} -ge ${expiration_date} ];
then
    # IF expiration date in the next 30 days rest password
    sp_id=$(az aks show -g ${resource_group} -n ${cluster_name} --query servicePrincipalProfile.clientId -o tsv)
    service_principle_secret=$(az ad sp credential reset --name ${sp_id} --end-date $(date -d "+ 90 days"  +%Y-%m-%d) --query password -o tsv)

    # Update cluster with new password
    az aks update-credentials \
    --resource-group ${resource_group} \
    --name ${cluster_name} \
    --reset-service-principal \
    --service-principal ${sp_id} \
    --client-secret ${service_principle_secret}
fi

答案 2 :(得分:-1)

我认为更好的方法是:

  1. 您的 terraform 代码很可能包含在一个更大的进程中。很可能您使用 bash 来启动该过程,然后进行 terraform。如果没有 - 我建议您这样做,因为这是使用 terraform 的最佳做法。
  2. 在运行 terraform 之前的 bash 代码中,例如,使用 az cli 检查相关服务主体的到期时间。 (无所谓)
  3. 如果已过期,请使用 terraform taint 命令将服务主体密码资源标记为受污染。我没有详细信息,也许您也需要污染服务主体。也许不是。
  4. 如果受到污染,terraform 将重新创建资源并重新生成密码。