我正在部署一个 awscloudformaton 模板来自动与 Active Directory 中的用户一起管理 Amazon Workspaces 生命周期
我正在关注一篇文章来做到这一点。但是我在部署它时遇到了错误。
检测到 1 个验证错误:“targets.1.member.values”中的值“[]”未能满足约束:成员必须满足约束:[成员的长度必须小于或等于 300,成员的长度必须大于或等于to 1](服务:AmazonSSM;状态代码:400;错误代码:ValidationException;请求 ID:cdf3c71c-9059-4e7e-a818-7e87f6e17385;代理:null)
cloudformation代码如下
AWSTemplateFormatVersion:“2010-09-09”描述:“此 CloudFormation 模板创建了一个解决方案,可根据 AD OU 中用户的存在来自动化 Amazon WorkSpaces 实例生命周期。”
模板参数参数:
S3 存储桶唯一名称 UsersBucketName:
Type: String Description: 'xxx-ws-dr-bucket-080119'
域控制器或成员服务器实例 ID AdInstanceID:
Type: String Description: 'i-078faa4q745c032dg'
WorkSpaces 用户 UsersOU 的 OU 路径:
Type: String Description: 'CN=workspace,CN=Users,DC=abc,DC=com'
AD 连接器或 Microsoft AD 目录 ID DirectoryID:
Type: String Description: 'd-90674434b6'
WorkSpaces 捆绑包 ID BundleID:
Type: String Description: 'wsb-clj83ezj1'
PS1 脚本 DriveLetter 的 Windows 驱动器:
Type: String Description: 'C' Resources:
创建 S3 存储桶 UsersBucket:
Type: AWS::S3::Bucket Properties: BucketName: !Ref UsersBucketName NotificationConfiguration: LambdaConfigurations: - Event: 's3:ObjectCreated:Put' Function: !GetAtt LambdaCompare.Arn Filter: S3Key: Rules: - Name: suffix Value: .csv DependsOn: - LambdaComparePermission
创建维护窗口角色MaintenanceWindowRole:
Type: AWS::IAM::Role Properties: RoleName: 'ws-automation-window-role' AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ssm.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonSSMMaintenanceWindowRole Policies: - PolicyName: pass-role PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - iam:PassRole Resource: - '*'
创建维护窗口MaintenanceWindow:
Type: AWS::SSM::MaintenanceWindow Properties: Name: 'ws-automation-maintenance-window' Schedule: 'cron(0 */5 * ? * *)' Duration: 3 Cutoff: 1 AllowUnassociatedTargets: true DependsOn: - MaintenanceWindowRole - UsersBucket
创建维护窗口任务MaintenanceWindowTask:
Type: AWS::SSM::MaintenanceWindowTask Properties: Name: 'ws-automation-maintenance-window-task' WindowId: !Sub '${MaintenanceWindow}' Targets: - Key: InstanceIds Values: - !Ref AdInstanceID TaskType: 'RUN_COMMAND' ServiceRoleArn: !GetAtt MaintenanceWindowRole.Arn TaskArn: 'AWS-RunPowerShellScript' TaskInvocationParameters: MaintenanceWindowRunCommandParameters: Parameters: commands: - !Sub "New-Item -Path ${DriveLetter}:\\workspaces-users -ItemType directory\nGet-ADUser -Filter * -SearchBase '${UsersOU}' -Properties SamAccountname | % {New-Object PSObject -Property @{oSamAccountname= $_.SamAccountname}} | Select oSamAccountname |
export-CSV ${DriveLetter}:\workspaces-users\workspaces-users1.csv -NoTypeInformation -Encoding UTF8\nGet-Content ${DriveLetter}:\workspaces-users\workspaces-users1.csv | 选择 - 跳过 1 | 设置内容 ${DriveLetter}:\workspaces-users\workspaces-users.csv\nWrite-S3Object -BucketName ${UsersBucketName} -File ${DriveLetter}:\workspaces-users\workspaces-users.csv" workingDirectory: - " " executionTimeout: - "3600" MaxConcurrency: 1 MaxErrors: 1 Priority: 10 DependsOn: - MaintenanceWindow
为 Lambda 比较函数 LambdaCompareRole 创建角色:
Type: AWS::IAM::Role Properties: RoleName: 'ws-automation-lambda-compare-role' AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Principal: Service: - 'lambda.amazonaws.com' Action: - 'sts:AssumeRole'
为 Lambda 比较函数 LambdaCompareRolePolicy 创建策略并附加到角色:
Type: AWS::IAM::Policy Properties: PolicyName: 'ws-automation-lambda-compare-role-policy' PolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Action: - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' - 'workspaces:CreateWorkspaces' - 'workspaces:TerminateWorkspaces' - 'workspaces:DescribeWorkspaces' Resource: '*' - Effect: 'Allow' Action: - 's3:PutObject' - 's3:GetObject' Resource: !Sub '${UsersBucket.Arn}/*' Roles: - !Ref LambdaCompareRole
创建 Lambda 比较函数 LambdaCompare:
Type: AWS::Lambda::Function Properties: FunctionName: 'ws-automation-lambda-compare' Handler: 'index.lambda_handler' Role: !Sub '${LambdaCompareRole.Arn}' Code: ZipFile: "Fn::Sub": | import csv import logging import os import boto3 s3_client = boto3.client('s3') ws_client = boto3.client('workspaces') DIRECTORY_ID = os.getenv('DIRECTORY_ID') BUNDLE_ID = os.getenv('BUNDLE_ID',) RUNNING_MODE = 'AUTO_STOP' logging.basicConfig(format='%(asctime)s [%(levelname)+8s]%(module)s: %(message)s', datefmt='%Y-%m-%d
%H:%M:%S') 记录器 = logging.getLogger(名称) logger.setLevel(getattr(logging, os.getenv('LOG_LEVEL', 'INFO'))) # --- 主处理程序 --- def lambda_handler(event, context): bucket = event['Records'][0 ]['s3']['bucket']['name'] key = event['Records'][0]['s3']['object']['key'] # 从 S3 获取 CSV 文件并转换它变成 JSON csv_object = s3_client.get_object(Bucket=bucket, Key=key) csv_users = csv.reader(csv_object['Body'].read().decode('utf-8').splitlines()) ad_users = set () for item in csv_users: if item: logger.debug('Adding user: {}'.format(item[0])) ad_users.add(item[0]) # 获取当前工作区 response = ws_client.describe_workspaces() workspaces = response['Workspaces'] current_ws = set() for workspaces in workspaces: current_ws.add(workspace['UserName']) # 如果用户在广告用户列表中但不在 WorkSpaces 列表中,则终止 WorkSpace users_to_add = ad_users - current_ws logger.debug('Users to add: {}'.format(users_to_add)) for user in users_to_add: try: logger .info('为用户创建工作区:{}'.format(user)) create_ws = ws_client.create_workspaces( Workspaces=[ { 'DirectoryId': DIRECTORY_ID, 'UserName': user, 'BundleId': BUNDLE_ID, 'WorkspaceProperties': { 'RunningMode': RUNNING_MODE, 'RunningModeAutoStopTimeoutInMinutes': 60 } } ] ) 例外为 e: logger.error('Unable to Create Workspaces') logger.debug('Error: {}'.format(e)) # If用户存在于 WorkSpaces 列表中但不在 AD 用户列表中,终止 WorkSpace ws_to_terminate = current_ws - ad_users logger.debug('Workspaces to terminate: {}'.format(ws_to_terminate)) for user in ws_to_terminate: try: logger.info('Terminating Workspaces for user: {}'.format(user)) describe_ws = ws_client.describe_workspaces( DirectoryId=DIRECTORY_ID, UserName=user ) workspace_id = describe_ws[' Workspaces'][0]['WorkspaceId'] terminate_ws = ws_client.terminate_workspaces( TerminateWorkspaceRequests=[ { 'WorkspaceId': workspace_id }, ]) 例外为 e: logger.error('Error execution describe_workspaces or terminate_workspaces') logger.debug ('错误:{}'.format(e))运行时:'python2.7'超时:600环境:变量:DIRECTORY_ID:!Ref DirectoryID BUNDLE_ID:!Ref BundleIDdescribe_workspaces( DirectoryId=DIRECTORY_ID, UserName=user ) workspace_id = describe_ws['Workspaces'][0]['WorkspaceId'] terminate_ws = ws_client.terminate_workspaces( TerminateWorkspaceRequests=[ { 'WorkspaceId': workspace_id }, ]) 例外为 e: logger.error('Error execution describe_workspaces or terminate_workspaces') logger.debug('Error: {}'.format(e)) Runtime: 'python2.7' Timeout: 600 Environment: Variables: DIRECTORY_ID: !Ref DirectoryID BUNDLE_ID: !参考 BundleIDdescribe_workspaces( DirectoryId=DIRECTORY_ID, UserName=user ) workspace_id = describe_ws['Workspaces'][0]['WorkspaceId'] terminate_ws = ws_client.terminate_workspaces( TerminateWorkspaceRequests=[ { 'WorkspaceId': workspace_id }, ]) 例外为 e: logger.error('Error execution describe_workspaces or terminate_workspaces') logger.debug('Error: {}'.format(e)) Runtime: 'python2.7' Timeout: 600 Environment: Variables: DIRECTORY_ID: !Ref DirectoryID BUNDLE_ID: !参考 BundleID错误执行 describe_workspaces 或 terminate_workspaces') logger.debug('Error: {}'.format(e)) Runtime: 'python2.7' Timeout: 600 Environment: Variables: DIRECTORY_ID: !Ref DirectoryID BUNDLE_ID: !Ref BundleID错误执行 describe_workspaces 或 terminate_workspaces') logger.debug('Error: {}'.format(e)) Runtime: 'python2.7' Timeout: 600 Environment: Variables: DIRECTORY_ID: !Ref DirectoryID BUNDLE_ID: !Ref BundleID
为 S3 存储桶 LambdaComparePermission 创建 Lambda 比较函数权限:
Type: AWS::Lambda::Permission Properties: FunctionName: !Ref LambdaCompare Action: 'lambda:InvokeFunction' Principal: 's3.amazonaws.com' SourceAccount: !Ref 'AWS::AccountId' SourceArn: !Sub 'arn:aws:s3:::${UsersBucketName}'
资源输出输出:堆栈名称:
Description: Stack name. Value: !Sub '${AWS::StackName}' UsersBucket: Description: S3 bucket name. Value: !Ref UsersBucket MaintenanceWindowRole: Description: Maintenance Window Role name. Value: !Ref MaintenanceWindowRole MaintenanceWindow: Description: Systems Manager Maintenance Window ID. Value: !Ref MaintenanceWindow MaintenanceWindowTask: Description: Maintenance Window Task ID. Value: !Ref MaintenanceWindowTask LambdaCompareRole: Description: Lambda Compare Role name. Value: !Ref LambdaCompareRole LambdaCompareRolePolicy: Description: Lambda Compare Policy ID. Value: !Ref LambdaCompareRolePolicy LambdaCompare: Description: Lambda Compare function name. Value: !Ref LambdaCompare
我只是想知道我在这里做错了什么以及需要改变什么。