Beispiel #1
0
def smtp_credentials(dnsname):
    if dnsname == 'localhost':
        user_name = f'ses-user-{dnsname}-{uuid.uuid4()}'
    else:
        user_name = f'ses-user-{dnsname}'
    code, output = shell.execute(
        f'aws iam create-user --user-name {user_name} --profile {config.PROFILE} --output json'
    )
    logging.debug(output)
    code, output = shell.execute(
        'aws iam put-user-policy --policy-document \'{"Version": "2012-10-17",'
        '"Statement":[{"Effect": "Allow","Action": "ses:SendRawEmail","Resource": "*"}]}\''
        f' --policy-name OpenRemoteSendEmail --user-name {user_name} --profile {config.PROFILE}'
    )
    code, output = shell.execute(
        f'aws iam create-access-key --user-name {user_name} --profile {config.PROFILE} --output json'
    )
    if config.DRY_RUN:
        return 'AccessKeyId', 'SecretAccessKey'
    else:
        logging.debug(output)
        access = json.loads(output)
        return (
            access['AccessKey']['AccessKeyId'],
            gen_aws_smtp_credentials.calculate_key(
                access['AccessKey']['SecretAccessKey'], config.REGION),
        )
Beispiel #2
0
def map_upload(path):
    shell.execute(
        f'aws s3 cp {path} s3://{config.BUCKET}/{path} --profile {config.PROFILE}',
        echo=True,
    )
    shell.execute(
        'aws s3api put-object-tagging --bucket %s --key %s --tagging \'TagSet=[{Key=type,Value=deployment-data}]\' --profile %s'
        % (config.BUCKET, path, config.PROFILE),
        echo=True,
    )
Beispiel #3
0
def remove(dnsname):
    if dnsname == 'localhost':
        shell.execute(f'docker stack rm openremote')
    else:
        if config.VERBOSE is True:
            print(f'> wget -nc {GITPATH}/mvp-docker-compose.yml')
        if not config.DRY_RUN:
            wget.download(f'{GITPATH}/mvp-docker-compose.yml')
        shell.execute(
            f'docker-compose -f mvp-docker-compose.yml -p openremote down')
Beispiel #4
0
def configure_aws_show():
    if not config.QUIET:
        print(f'S3 bucket: s3://{config.BUCKET}\n')
        region = shell.execute(
            f'aws configure get region --profile {config.PROFILE}')[1][:-1]
        id = shell.execute(
            f'aws configure get aws_access_key_id --profile {config.PROFILE}'
        )[1][:-1]
        secret = shell.execute(
            f'aws configure get aws_secret_access_key --profile {config.PROFILE}'
        )[1][:-1]
        print(f'--id={id} --secret="{secret}" --region={region}')
Beispiel #5
0
def deploy_rich(password, smtp_user, smtp_password, project):
    staging = False
    if project.find('staging.') == 0:
        staging = True
        project = project[8:]
    shell.execute(
        f'aws s3 cp s3://{config.BUCKET}/{project} {project} --storage-class STANDARD --recursive --profile {config.PROFILE} --force-glacier-transfer'
    )
    shell.execute(f'tar xvf {project}/deployment.tar.gz')
    shell.execute(f'mv mapdata.mbtiles deployment/map/', no_exception=True)
    env = ''
    # TODO reuse installed credentials docker run {project_manager_1} env
    if password != 'secret':
        env = f'PASSWORD={password} '
    if smtp_user and smtp_password:
        env = (f'{env}EMAIL_USER={smtp_user} '
               f'EMAIL_PASSWORD={smtp_password} '
               f'EMAIL_HOST=email-smtp.{config.REGION}.amazonaws.com ')
    dnsname = f'{project}.openremote.io'
    if staging:
        env = f'{env}DEPLOYMENT_NAME=staging.{project} '
    else:
        env = f'{env}DEPLOYMENT_NAME={project} '
    generate_password, password = _password(password, url=dnsname)
    if generate_password:
        env = f'{env}PASSWORD={password} '
    shell.execute(f'{env}docker-compose up -d')
    if not config.DRY_RUN:
        print('\nStack deployed, waiting for startup to complete', end=' ')
        while _deploy_health(dnsname, 0) == 0:
            time.sleep(3)
            print('.', end='', flush=True)
        print(emojis.encode(':thumbsup:'))
    if config.VERBOSE is True:
        print(f'\nOpen https://{dnsname} and login with admin:{password}')
Beispiel #6
0
def check_aws_perquisites():
    # Check AWS profile
    code, output = shell.execute('aws configure list-profiles')
    if not config.DRY_RUN and config.PROFILE not in output:
        msg = f"aws-cli profile '{config.PROFILE}' missing"
        raise Exception(-1, msg)
    # Check EC2 key
    code, output = shell.execute(
        f'aws ec2 describe-key-pairs --key-names openremote --profile {config.PROFILE}'
    )
    if not config.DRY_RUN and 'openremote' not in output:
        msg = f"ERROR: Missing EC2 keypair 'openremote' in {config.REGION} region (Ireland)"
        raise Exception(-1, msg)
    return True
Beispiel #7
0
def remove_aws(dnsname):
    check_aws_perquisites()
    if os.name == "nt":
        if config.VERBOSE:
            print(f'del aws-delete-stack-{dnsname}.bat')
        shell.execute(f'aws-delete-stack-{dnsname}.bat')
        if not config.DRY_RUN:
            os.remove(f'aws-delete-stack-{dnsname}.bat')
    else:
        if config.VERBOSE:
            print(f'rm aws-delete-stack-{dnsname}.sh')
        shell.execute(f'sh aws-delete-stack-{dnsname}.sh')
        if not config.DRY_RUN:
            os.remove(f'aws-delete-stack-{dnsname}.sh')
Beispiel #8
0
 def _show_check_result(tool):
     code, output = shell.execute(tool, no_exception=True)
     if not config.QUIET:
         print(f'{output.rstrip()} ', end='')
         print(emojis.encode(':heavy_check_mark:')) if code == 0 else print(
             emojis.encode(':x:'))
     elif code != 0:
         raise Exception(f'{code}, {output}')
Beispiel #9
0
def clean():
    shell.execute(
        'docker volume rm --force openremote_deployment-data openremote_postgresql-data openremote_proxy-data'
    )
    shell.execute(
        'docker rmi openremote/manager-swarm openremote/deployment '
        'openremote/keycloak openremote/postgresql openremote/proxy '
        'openremote/manager',
        no_exception=True,
    )
    shell.execute('docker system prune --force')
Beispiel #10
0
def configure_aws(id, secret, region):
    config.REGION = region
    shell.execute(
        f'aws configure set profile.{config.PROFILE}.aws_access_key_id {id}',
        echo=config.VERBOSE,
    )
    shell.execute(
        f'aws configure set profile.{config.PROFILE}.aws_secret_access_key {secret}',
        echo=config.VERBOSE,
    )
    shell.execute(
        f'aws configure set profile.{config.PROFILE}.region {region}',
        echo=config.VERBOSE,
    )
Beispiel #11
0
def map_delete(path):
    shell.execute(
        # No --recursive here as it can wipe the whole bucket, also for other clients
        f'aws s3 rm s3://{config.BUCKET}/{path} --profile {config.PROFILE}',
        echo=True,
    )
Beispiel #12
0
def map_download(path):
    shell.execute(
        f'aws s3 cp s3://{config.BUCKET}/{path} {path} --storage-class STANDARD --recursive --profile {config.PROFILE} --force-glacier-transfer',
        echo=True,
    )
Beispiel #13
0
def map_list(path):
    shell.execute(
        f'aws s3 ls s3://{config.BUCKET}/{path} --recursive --human-readable --summarize --profile {config.PROFILE}',
        echo=True,
    )
Beispiel #14
0
def deploy(password, smtp_user, smtp_password, dnsname):
    shell.execute('docker swarm init', no_exception=True)
    shell.execute('docker volume rm openremote_postgresql-data',
                  no_exception=True)
    # TODO fetch tar from S3 and copy to the docker volume
    # shell.execute('docker volume create openremote_deployment-data')
    # shell.execute(
    #     'docker run --rm -v openremote_deployment-data:/deployment openremote/deployment:mvp'
    # )
    if config.VERBOSE is True:
        print(f'> wget -nc {GITPATH}/mvp-docker-compose.yml')
    if not config.DRY_RUN:
        wget.download(f'{GITPATH}/mvp-docker-compose.yml')
    env = ''
    if password != 'secret':
        env = f'PASSWORD={password} '
    if smtp_user and smtp_password:
        env = (f'{env}EMAIL_USER={smtp_user} '
               f'EMAIL_PASSWORD={smtp_password} '
               f'EMAIL_HOST=email-smtp.{config.REGION}.amazonaws.com ')
    if True:
        identity = dnsname
        if _check_ip(dnsname):  # it is pure IP
            dnsname = 'localhost'  # prevent proxy from issuing cert
        env = f'{env}DOMAINNAME={dnsname} IDENTITY_NETWORK_HOST={identity} '
        # As you may be facing internet change default password for security
        generate_password, password = _password(password, url=dnsname)
        if generate_password:
            env = f'{env}PASSWORD={password} '
        # Deploy with docker-compose as proxy container does not obey
        # health check within swarm mode
        # TODO revisit proxy image to fix this, otherwise letsencrypt has problems
        shell.execute(
            f'{env}docker-compose -f mvp-docker-compose.yml -p openremote up -d'
        )
        if not config.DRY_RUN:
            print('\nStack deployed, waiting for startup to complete', end=' ')
            while _deploy_health(dnsname, 0) == 0:
                time.sleep(3)
                print('.', end='', flush=True)
            print(emojis.encode(':thumbsup:\n'))
        if config.VERBOSE is True:
            print(
                f'Open https://{dnsname} and login with admin:{password}\n\n'
                'Remove the stack when you are done:\n'
                '> docker-compose -f mvp-docker-compose.yml -p openremote down\n'
                '> rm mvp-docker-compose.yml\n')
    else:
        shell.execute(
            f'{env}docker stack deploy -c mvp-docker-compose.yml openremote')
        if not config.DRY_RUN:
            print('\nStack deployed, waiting for startup to complete', end=' ')
            c = 0
            # TODO deploying from docker image has problems with health checking hence 10min time out
            while _deploy_health(dnsname, 0) == 0 and c < 200:
                time.sleep(3)
                print('.', end='', flush=True)
                c += 1
            print(emojis.encode(':thumbsup:\n'))
        if config.VERBOSE is True:
            print(
                f'\nOpen https://localhost and login with admin:{password}\n\n'
                'To remove the stack when you are done:\n'
                '> docker stack rm openremote\n')
        if not config.DRY_RUN:
            os.remove(f'mvp-docker-compose.yml')
    if config.VERBOSE is True:
        print(
            'To remove docker resources:\n'
            "> docker images --filter 'reference=openremote/*' -q | xargs docker rmi\n"
            "> docker volume ls --filter 'dangling=true' -q | xargs docker volume rm"
        )
Beispiel #15
0
def deploy_aws(password, dnsname, region):
    host, domain = _split_dns(dnsname)
    logging.debug(f'{dnsname} => {host} + {domain}')
    stack_name = f'{host}-{uuid.uuid4()}'
    check_aws_perquisites()
    generate_password, password = _password(password, url=dnsname)
    if config.VERBOSE is True:
        print(f'> wget -nc {GITPATH}/aws-cloudformation.template.yml')
    if not config.DRY_RUN:
        wget.download(f'{GITPATH}/aws-cloudformation.template.yml')
    shell_exec = shell.execute(
        f'aws cloudformation create-stack --stack-name {stack_name} '
        f'--template-body file://aws-cloudformation.template.yml --parameters '
        f'ParameterKey=DomainName,ParameterValue={domain} '
        f'ParameterKey=HostName,ParameterValue={host} '
        f'ParameterKey=HostedZone,ParameterValue=true '
        f'ParameterKey=OpenRemotePassword,ParameterValue={password} '
        f'ParameterKey=InstanceType,ParameterValue=t4g.small '
        f'--capabilities CAPABILITY_NAMED_IAM '
        f'--profile={config.PROFILE} '
        f'--disable-rollback '
        f'--region={region}')
    print(f'\n{shell_exec[1]}')
    if shell_exec[0] != 0:
        raise Exception(shell_exec)

    print('Waiting for CloudFormation...')
    # TODO make better feedback to the user
    # code, output = shell.execute
    # CREATE_STACK_STATUS=$(aws --region ${AWS_REGION} --profile ${AWS_PROFILE} cloudformation describe-stacks --stack-name ${STACK_NAME} --query 'Stacks[0].StackStatus' --output text)
    # while [[ $CREATE_STACK_STATUS == "REVIEW_IN_PROGRESS" ]] || [[ $CREATE_STACK_STATUS == "CREATE_IN_PROGRESS" ]]
    # do
    #     # Wait 30 seconds and then check stack status again
    #     sleep 30
    #     CREATE_STACK_STATUS=$(aws --region ${AWS_REGION} --profile ${AWS_PROFILE} cloudformation describe-stacks --stack-name ${STACK_NAME} --query 'Stacks[0].StackStatus' --output text)
    # done
    shell.execute(
        f'aws cloudformation wait stack-create-complete '
        f'--stack-name {stack_name} --profile {config.PROFILE} --region={region}'
    )
    if not config.DRY_RUN:
        os.remove(f'aws-cloudformation.template.yml')
        if generate_password:
            # In case of password generation get email credentials and send it to support
            code, output = shell.execute(
                f'aws cloudformation describe-stacks --stack-name {stack_name} --profile {config.PROFILE} --region={region} '
                '--query "Stacks[0].Outputs[?OutputKey==\'UserId\'||OutputKey==\'UserSecret\'].OutputValue" --output json'
            )
            credentials = json.loads(output)
            smtp_user = credentials[0]
            smtp_password = gen_aws_smtp_credentials.calculate_key(
                credentials[1], config.REGION)
            email.sendmail(
                "*****@*****.**",
                "Openremote password",
                f"""
                A new AWS stack {stack_name} has been just created. Because there was a
                default password used a more secure one was generated. The new admin password is
                {password}
                """,
                smtp_user,
                smtp_password,
            )
            print(
                '\nAn email with generated password was sent to [email protected]\n'
            )
    elif generate_password:
        print(
            '\nAn email with generated password would be sent to [email protected]\n'
        )
    if not config.DRY_RUN:
        if os.name == "nt":
            shell.execute(
                f'echo "aws cloudformation delete-stack --stack-name {stack_name} --profile {config.PROFILE} --region={region}" > aws-delete-stack-{host}.{domain}.bat'
            )
        else:
            shell.execute(
                f'echo "aws cloudformation delete-stack --stack-name {stack_name} --profile {config.PROFILE} --region={region}" > aws-delete-stack-{host}.{domain}.sh'
            )
            shell.execute(f'chmod +x aws-delete-stack-{host}.{domain}.sh')
        print('\nStack deployed, waiting for startup to complete', end=' ')
        c = 0
        while _deploy_health(f'{host}.{domain}', 0) == 0 and c < 200:
            time.sleep(3)
            print('.', end='', flush=True)
            c += 1
        print(emojis.encode(':thumbsup:\n'))
    print(
        emojis.encode(
            '\nMind that running it cost money :moneybag::moneybag::moneybag:! To free resources execute:\n\n'
            f'aws cloudformation delete-stack --stack-name {stack_name} --profile {config.PROFILE} --region={region}\n\n'
            'check running stack with health command:\n'
            f'or deploy -a health --dnsname {host}.{domain} -v'))