דלג לתוכן הראשי

יצירת ססמאות רנדומאליות באמצעות טרהפורם

יצירת ססמאות עבור משאבים בענן תוך שימוש בטרהפורם הוא דורש שימוש במשאב שנקרא random_password שמסופק על ידי טרהפורם (ולא ספקי הענן). מטרת המאמר הוא ליצור מודול עבור מטלה של יצירת ססמאות לכל משאב.

יצירת סיסמה מורכבת

בקוד דלהלן אנו מגדירים ססמה בת 16 תווים עם תווים מיוחדים מספרים אותיות קטנות וגדולות:

resource "random_password" "this" {
length = 16
special = true
upper = true
lower = true
numeric = true
override_special = "!@#%^&*"
}

ובקובץ ה- outputs.tf אנו מציינים כי הערך הנוצר מהמשאב random_password הוא סודי, ולכן הוא לא יחשוף אותו בפלט בקונסול.

output "generated_password" {
value = random_password.this.result
sensitive = true
}
זהירות

למרות שבפלט לקונסול לא תוצג הססמה, היא עדיין תישמר בקובץ terraform state. לכן כדאי לשמור את הקובץ state בשרת מרוחק עם הצפנה, כדוגמת AWS S3.

ישנם עוד פתרונות כדי למנוע את כתיבת הססמה בקובץ state כדוגמת AWS Secret Manager.

ססמה באורך משתנה

כמובן שלא נרצה לקבוע את ערך מספר התווים כ- Hard Coded בקוד. לכן ניתן להגדיר זאת כמשתנה שבו נגדיר את האורך. הדוגמה הבאה מממשת את הלוגיקה:

provider "random" {}

variable "password_length" {
description = "Length of the generated password"
type = number
default = 16
}

resource "random_password" "dynamic_password" {
length = var.password_length
special = true
upper = true
lower = true
numeric = true
}

output "generated_password" {
value = random_password.dynamic_password.result
sensitive = true
}

הסבר הבלוקים:

  1. בבלוק provider אנו קוראים לספק של טרהפורם שיביא לנו את הפלאגין שיוצר את הפונקציה של ססמה דינאמית.
  2. בבלוק variable אנו מגדירים משתנה שבו אנו מזינים את הערך של מספר התווים של הססמה.
  3. בבלוק resource אנו מגדירים את אורך הססמה (בהפניה למשתנה) ומורכבות הססמה.
  4. בבלוק output אנו מורים לטרהפורם לשמור את הססמה הנוצרת כסוד ולא לכתוב אותה בפלט.

יצירת ססמאות עבור משתמשים מרובים

כדי ליצור למספר משתמשים ססמאות שונות, נשתמש בפונקציה for_each ובהפניה לרשימת המשתמשים המאוחסנת במשתנים. כדלהלן:

provider "random" {}

variable "users" {
description = "List of users who need passwords"
type = list(string)
default = ["alice", "bob", "charlie"]
}

resource "random_password" "user_passwords" {
for_each = toset(var.users)

length = 16
special = true
upper = true
lower = true
numeric = true
}

output "user_passwords" {
value = { for user in var.users : user => random_password.user_passwords[user].result }
sensitive = true
}

הסבר ופירוט:

  1. בבלוק variable הגדרנו משתנה מיוחד מסוג list המכיל string. ברשימה זו אנו כותבים את שמות המשתמשים.
  2. בבלוק resource יש הנחיה ליצירת ססמה רנדומלית עבור כל (for_each) משתמש, ופונקציה של toset המקבלת את רשימת המחרוזות וממירה לקבוצת שמות כאשר נוצר לכל משתמש ססמה ייחודית.
  3. בבלוק output אנו שוב משתמשים בפונקציה מיוחדת העוברת על כל מחרוזת במשתנה var.users ומחילה על כל הקבוצה את ההגדרה של sensitive = true.

איחסון הססמה

כאמור לעיל לא מומלץ לשמור את הססמה כתובה בקובץ הסטייט. לכן הפתרון הוא להשתמש ב- AWS Secret Manager. להלן קוד המממש את העיקרון:

provider "aws" {
region = "il-central-1"
}

provider "random" {}

# Generate a random password
resource "random_password" "db_password" {
length = 20
special = true
upper = true
lower = true
numeric = true
}

# Create a secret in AWS Secrets Manager
resource "aws_secretsmanager_secret" "db_secret" {
name = "my-database-password"
}

# Store the generated password in AWS Secrets Manager
resource "aws_secretsmanager_secret_version" "db_secret_value" {
secret_id = aws_secretsmanager_secret.db_secret.id
secret_string = jsonencode({
username = "admin"
password = random_password.db_password.result
})
}

output "secret_arn" {
value = aws_secretsmanager_secret.db_secret.arn
}

הסבר על הקטעים שנוספו:

  1. הבלוק provider aws מגדיר את הספק AWS.
  2. הבלוק secret manager יוצר את המשאב בענן של AWS.
  3. הבלוק aws_secretsmanager_secret_version מגדיר: שם לסוד, ערך לשם המשתמש, וססמה כאשר היא מתקבלת מהתוצאה של ה- random_password.