יצירת ססמאות רנדומאליות באמצעות טרהפורם
יצירת ססמאות עבור משאבים בענן תוך שימוש בטרהפורם הוא דורש שימוש במשאב שנקרא
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
}
הסבר הבלוקים:
- בבלוק
providerאנו קוראים לספק של טרהפורם שיביא לנו את הפלאגין שיוצר את הפונקציה של ססמה דינאמית. - בבלוק
variableאנו מגדירים משתנה שבו אנו מזינים את הערך של מספר התווים של הססמה. - בבלוק
resourceאנו מגדירים את אורך הססמה (בהפניה למשתנה) ומורכבות הססמה. - בבלוק
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
}
הסבר ופירוט:
- בבלוק
variableהגדרנו משתנה מיוחד מסוגlistהמכילstring. ברשימה זו אנו כותבים את שמות המשתמשים. - בבלוק
resourceיש הנחיה ליצירת ססמה רנדומלית עבור כל (for_each) משתמש, ופונקציה שלtosetהמקבלת את רשימת המחרוזות וממירה לקבוצת שמות כאשר נוצר לכל משתמש ססמה ייחודית. - בבלוק
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
}
הסבר על הקטעים שנוספו:
- הבלוק
provider awsמגדיר את הספק AWS. - הבלוק
secret managerיוצר את המשאב בענן של AWS. - הבלוק
aws_secretsmanager_secret_versionמגדיר: שם לסוד, ערך לשם המשתמש, וססמה כאשר היא מתקבלת מהתוצאה של ה-random_password.