0

我正在部署一个 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

我只是想知道我在这里做错了什么以及需要改变什么。

4

0 回答 0