本頁說明如何將 ONTAP 模式集區加入 Active Directory 網域。
ONTAP 模式的 Flex Unified 儲存空間集區不會使用 Active Directory 政策。如要搭配使用 Active Directory 和 SMB 磁碟區,請建立 CIFS 伺服器,將集區中的 ONTAP 儲存空間虛擬機器 (SVM) 加入 Windows 網域。
如要瞭解 Active Directory 的必要條件和防火牆規則,請參閱「Google Cloud NetApp Volumes Active Directory 整合」。
事前準備
完成下列必要條件:
確認儲存集區網路可以連線至網域控制站和 DNS 伺服器。
設定 Cloud DNS,將 Windows 網域的 DNS 要求轉送至 Windows DNS 伺服器。
完成「事前準備」中的必備條件。
請收集以下資訊:
AD_FQDN:完整網域名稱,例如 corp.example.com。AD_DNS_SERVERS:以半形逗號分隔的一到三個 IPv4 位址,適用於 Active Directory DNS 伺服器。AD_USERNAME和AD_PASSWORD:可建立電腦帳戶的網域帳戶,且 SAM 帳戶名稱最多 20 個字元。COMPUTER_NAME:網域中電腦帳戶的不重複 NetBIOS 名稱,最多 15 個字元。OU:選用:目標組織單位 (OU) 的辨別名稱,例如 OU=Computers,DC=corp,DC=example,DC=com。
總覽
如要將 ONTAP 模式集區加入 Active Directory 網域,請完成下列步驟:
查詢集區資源
查閱儲存空間集區的下列資源:
SVM 名稱
如要查詢 SVM 名稱,請按照下列步驟操作:
ontap_execute "vserver show -fields vserver,operational-state"
請記下 Vserver 名稱,例如 gcnv-7cf6ee41c1a94f0-svm-01。後續步驟會使用這個名稱做為 SVM_NAME。
資料 LIF
加入網域前,請先確認資料 LIF 能順利連線至 DNS 伺服器和網域控制站。
ontap_execute "network interface show -role data"
如要測試與 DNS 伺服器或網域控制器的連線,請使用 SAN LIF 並加上 -lif 旗標。ONTAP 模式集區會公開名為 SVM_NAME-san-1、SVM_NAME-san-2 的 SAN LIF,以及視需要公開其他 LIF:
ontap_execute "network ping -vserver SVM_NAME -destination DNS_OR_DC_IP -lif SVM_NAME-san-1"
如果 Ping 失敗,儲存集區就無法透過網路連線至 DNS 伺服器或網域控制站。虛擬私有雲中的虛擬機器 (VM) 可能仍可連線至這些主機。如要進一步瞭解如何排解連線問題,請參閱「Why your NetApp Volumes can't connect to Active Directory and other networks behind your VPC」。
在 SVM 上設定 DNS
如要在 SVM 上設定 DNS,請按照下列步驟操作:
ontap_execute "vserver services name-service dns create -vserver SVM_NAME -domains AD_FQDN -name-servers AD_DNS_SERVERS"
如果主機的名稱服務切換器未包含 DNS,請新增:
ontap_execute "vserver services name-service ns-switch modify -vserver SVM_NAME -database hosts -sources dns,files"
驗證設定:
ontap_execute "vserver services name-service dns show -vserver SVM_NAME"
加入網域
本節說明 ONTAP CLI 指令、CLI Proxy 的限制,以及如何使用 Python 加入網域。
ONTAP CLI 指令
在可直接存取 ONTAP CLI 的系統上,執行下列指令:
vserver cifs create -vserver SVM_NAME -cifs-server COMPUTER_NAME -domain AD_FQDN
如要加入選用參數,請使用 -ou OU 和 -default-site SITE。ONTAP 會提示您輸入網域密碼,這個指令可能需要幾分鐘才能完成。
CLI Proxy 的限制
ONTAP CLI Proxy 並非互動式,由於 vserver cifs create 命令會提示輸入密碼,因此您無法透過 Proxy 完成加入網域的程序。請改用 REST API。對應的 API 是 POST /protocols/cifs/services。
這個指令碼只會為與 Active Directory 的 Kerberos 通訊宣傳 AES-256。這是現代網域的建議設定。如要宣傳 AES-128 或 DES,請在執行指令碼前,將值新增至指令碼中的 advertised_kdc_encryptions 陣列,或在加入網域後使用 vserver cifs security modify -advertised-enc-types 修改 CIFS 伺服器。DES 使用的加密方式強度較弱,因此不建議使用。
加密類型有效值為 aes-256、aes-128、rc4 和 des。如果您在加入網域後變更宣傳的加密類型,ONTAP 會重設機器帳戶密碼,並提示您輸入 Active Directory 認證。
使用 Python 加入網域
將下列指令碼儲存為 join_ad.py,然後使用 Python 3.8 以上版本運作執行。指令碼只會使用 Python 標準程式庫。
#!/usr/bin/env python3
"""Join an ONTAP-mode SVM to Active Directory by creating a CIFS server."""
import json
import os
import subprocess
import sys
import time
import urllib.error
import urllib.request
# Required environment variables.
REQUIRED = (
"PROJECT_ID", "LOCATION", "POOL_NAME", "SVM_NAME",
"AD_FQDN", "COMPUTER_NAME", "AD_USERNAME", "AD_PASSWORD",
)
missing = [name for name in REQUIRED if not os.environ.get(name)]
if missing:
sys.exit(f"Set required environment variables: {', '.join(missing)}")
PROJECT_ID = os.environ["PROJECT_ID"]
LOCATION = os.environ["LOCATION"]
POOL_NAME = os.environ["POOL_NAME"]
SVM_NAME = os.environ["SVM_NAME"]
AD_FQDN = os.environ["AD_FQDN"]
COMPUTER_NAME = os.environ["COMPUTER_NAME"]
AD_USERNAME = os.environ["AD_USERNAME"]
AD_PASSWORD = os.environ["AD_PASSWORD"]
# Optional environment variables.
OU = os.environ.get("OU", "")
AD_SITE = os.environ.get("AD_SITE", "")
POLL_INTERVAL = int(os.environ.get("POLL_INTERVAL", "10"))
# Kerberos encryption types advertised to Active Directory. AES-256 only by default.
# To add aes-128 or des (not recommended), extend this list before you run the script.
ADVERTISED_KDC_ENCRYPTIONS = ["aes-256"]
API_ROOT = (
f"https://netapp.googleapis.com/v1/projects/{PROJECT_ID}"
f"/locations/{LOCATION}/storagePools/{POOL_NAME}/ontap/api"
)
def get_access_token() -> str:
return subprocess.check_output(
["gcloud", "auth", "print-access-token"], text=True
).strip()
def api_request(method: str, path: str, body=None) -> dict:
headers = {
"Authorization": f"Bearer {get_access_token()}",
"Content-Type": "application/json",
}
data = json.dumps(body).encode() if body is not None else None
req = urllib.request.Request(f"{API_ROOT}{path}", data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
except urllib.error.HTTPError as exc:
detail = exc.read().decode()
sys.exit(f"API request failed ({exc.code}): {detail}")
def job_record(response: dict) -> dict:
return response.get("rawResponse") or response.get("body") or response
def job_state(response: dict) -> str:
return job_record(response).get("state", "")
def format_job_error(response: dict) -> str:
record = job_record(response)
message = record.get("message") or record.get("error", {}).get("message")
if message:
return message
return json.dumps(response, indent=2)
def wait_for_job(job_uuid: str) -> None:
print(f"ONTAP job UUID: {job_uuid}")
while True:
response = api_request("GET", f"/cluster/jobs/{job_uuid}")
state = job_state(response)
print(f" Job state: {state}")
if state == "success":
print("Domain join completed.")
return
if state in ("failure", "error"):
sys.exit(f"Job failed: {format_job_error(response)}")
time.sleep(POLL_INTERVAL)
def main() -> None:
ad_domain = {
"fqdn": AD_FQDN,
"user": AD_USERNAME,
"password": AD_PASSWORD,
}
if OU:
ad_domain["organizational_unit"] = OU
if AD_SITE:
ad_domain["default_site"] = AD_SITE
body = {
"body": {
"svm": {"name": SVM_NAME},
"name": COMPUTER_NAME,
"ad_domain": ad_domain,
"security": {
"advertised_kdc_encryptions": ADVERTISED_KDC_ENCRYPTIONS,
},
}
}
print(f"Creating CIFS server and joining {AD_FQDN}...")
response = api_request("POST", "/protocols/cifs/services?return_records=true", body)
job = (response.get("body") or {}).get("job") or response.get("job")
if not job or not job.get("uuid"):
print(json.dumps(response, indent=2))
return
wait_for_job(job["uuid"])
if __name__ == "__main__":
main()
設定 SMB 存取權
將本機管理員權限授予網域使用者或群組:
ontap_execute "vserver cifs users-and-groups local-group add-members -vserver SVM_NAME -group-name BUILTIN\\Administrators -member-names NETBIOS_DOMAIN\\username"
將 NETBIOS_DOMAIN 替換為 NetBIOS 網域名稱,而非 DNS 名稱。
如果您使用與 Active Directory 整合的 DNS,請啟用安全動態 DNS 更新。
您必須將 -vserver-fqdn 旗標設為 CIFS 伺服器 FQDN,例如:COMPUTER_NAME.AD_FQDN
ontap_execute "vserver services name-service dns dynamic-update modify -vserver SVM_NAME -is-enabled true -use-secure true -vserver-fqdn COMPUTER_NAME.AD_FQDN"
驗證網域加入作業
如要驗證網域加入作業,請按照下列步驟操作:
ontap_execute "vserver cifs show -vserver SVM_NAME"
確認 CIFS 伺服器已連線,並加入預期網域。
移除 CIFS 伺服器
如要刪除 CIFS 伺服器並重新加入網域,請完成下列步驟:
停用安全動態 DNS 更新:
ontap_execute "vserver services name-service dns dynamic-update modify -vserver SVM_NAME -is-enabled false -use-secure false"
啟用安全 DDNS 時,ONTAP 會封鎖 CIFS 刪除作業。
從 Active Directory 移除電腦帳戶,或使用有權刪除目標 OU 中電腦帳戶的網域帳戶。
在 ONTAP 上刪除 CIFS 伺服器:
ontap_execute "vserver cifs delete -vserver SVM_NAME -skip-ad-account-delete true"
如果電腦帳戶已從 Active Directory 移除,或用於刪除作業的帳戶沒有權限移除電腦物件,請使用
-skip-ad-account-delete true。在本例中,ONTAP 只會移除本機 CIFS 設定,不會嘗試刪除 Active Directory 物件。根據預設,
vserver cifs delete也會從 Active Directory 移除電腦帳戶,並提示輸入網域管理員憑證。這個提示無法透過 ONTAP CLI Proxy 運作。
後續步驟
建立磁碟區 在集區中建立 SMB 磁碟區。