示例#1
0
def enable_mirroring_for_repository(
    repository,
    root_rule,
    internal_robot,
    external_reference,
    sync_interval,
    external_registry_username=None,
    external_registry_password=None,
    external_registry_config=None,
    is_enabled=True,
    sync_start_date=None,
):
    """
    Create a RepoMirrorConfig and set the Repository to the MIRROR state.
    """
    assert internal_robot.robot

    namespace, _ = parse_robot_username(internal_robot.username)
    if namespace != repository.namespace_user.username:
        raise DataModelException("Cannot use robot for mirroring")

    with db_transaction():
        # Create the RepoMirrorConfig
        try:
            username = (
                DecryptedValue(external_registry_username) if external_registry_username else None
            )
            password = (
                DecryptedValue(external_registry_password) if external_registry_password else None
            )
            mirror = RepoMirrorConfig.create(
                repository=repository,
                root_rule=root_rule,
                is_enabled=is_enabled,
                internal_robot=internal_robot,
                external_reference=external_reference,
                external_registry_username=username,
                external_registry_password=password,
                external_registry_config=external_registry_config or {},
                sync_interval=sync_interval,
                sync_start_date=sync_start_date or datetime.utcnow(),
            )
        except IntegrityError:
            return RepoMirrorConfig.get(repository=repository)

        # Change Repository state to mirroring mode as needed
        if repository.state != RepositoryState.MIRROR:
            query = Repository.update(state=RepositoryState.MIRROR).where(
                Repository.id == repository.id
            )
            if not query.execute():
                raise DataModelException("Could not change the state of the repository")

        return mirror
示例#2
0
def create_token(user, title, expiration=_default_expiration_duration_opt):
    """ Creates and returns an app specific token for the given user. If no expiration is specified
      (including `None`), then the default from config is used. """
    if expiration == _default_expiration_duration_opt:
        duration = _default_expiration_duration()
        expiration = duration + datetime.now() if duration else None

    token_code = random_string_generator(TOKEN_NAME_PREFIX_LENGTH +
                                         MINIMUM_TOKEN_SUFFIX_LENGTH)()
    token_name = token_code[:TOKEN_NAME_PREFIX_LENGTH]
    token_secret = token_code[TOKEN_NAME_PREFIX_LENGTH:]

    assert token_name
    assert token_secret

    # TODO(remove-unenc): Remove legacy handling.
    old_token_code = (token_code if ActiveDataMigration.has_flag(
        ERTMigrationFlags.WRITE_OLD_FIELDS) else None)
    return AppSpecificAuthToken.create(
        user=user,
        title=title,
        expiration=expiration,
        token_name=token_name,
        token_secret=DecryptedValue(token_secret),
        token_code=old_token_code,
    )
示例#3
0
def create_token(user, title, expiration=_default_expiration_duration_opt):
    """
    Creates and returns an app specific token for the given user.

    If no expiration is specified (including `None`), then the default from config is used.
    """
    if expiration == _default_expiration_duration_opt:
        duration = _default_expiration_duration()
        expiration = duration + datetime.now() if duration else None

    token_code = random_string_generator(TOKEN_NAME_PREFIX_LENGTH +
                                         MINIMUM_TOKEN_SUFFIX_LENGTH)()
    token_name = token_code[:TOKEN_NAME_PREFIX_LENGTH]
    token_secret = token_code[TOKEN_NAME_PREFIX_LENGTH:]

    assert token_name
    assert token_secret

    return AppSpecificAuthToken.create(
        user=user,
        title=title,
        expiration=expiration,
        token_name=token_name,
        token_secret=DecryptedValue(token_secret),
    )
示例#4
0
def update_build_trigger(trigger, config, auth_token=None, write_token=None):
    trigger.config = json.dumps(config or {})

    if auth_token is not None:
        trigger.secure_auth_token = DecryptedValue(auth_token)

    if write_token is not None:
        trigger.write_token = write_token

    trigger.save()
示例#5
0
文件: oauth.py 项目: zhill/quay
def reset_client_secret(application):
    client_secret = random_string_generator(length=40)()

    # TODO(remove-unenc): Remove legacy field.
    if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
        application.client_secret = client_secret

    application.secure_client_secret = DecryptedValue(client_secret)
    application.save()
    return application
示例#6
0
def create_application(org, name, application_uri, redirect_uri, **kwargs):
    client_secret = kwargs.pop("client_secret",
                               random_string_generator(length=40)())
    return OAuthApplication.create(
        organization=org,
        name=name,
        application_uri=application_uri,
        redirect_uri=redirect_uri,
        secure_client_secret=DecryptedValue(client_secret),
        **kwargs)
示例#7
0
def update_build_trigger(trigger, config, auth_token=None, write_token=None):
    trigger.config = json.dumps(config or {})

    # TODO(remove-unenc): Remove legacy field.
    if auth_token is not None:
        if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
            trigger.auth_token = auth_token

        trigger.secure_auth_token = DecryptedValue(auth_token)

    if write_token is not None:
        trigger.write_token = write_token

    trigger.save()
示例#8
0
def create_build_trigger(repo,
                         service_name,
                         auth_token,
                         user,
                         pull_robot=None,
                         config=None):
    service = BuildTriggerService.get(name=service_name)
    secure_auth_token = DecryptedValue(auth_token) if auth_token else None
    trigger = RepositoryBuildTrigger.create(
        repository=repo,
        service=service,
        secure_auth_token=secure_auth_token,
        connected_user=user,
        pull_robot=pull_robot,
        config=json.dumps(config or {}),
    )
    return trigger
示例#9
0
文件: oauth.py 项目: zhill/quay
def create_application(org, name, application_uri, redirect_uri, **kwargs):
    client_secret = kwargs.pop("client_secret",
                               random_string_generator(length=40)())

    # TODO(remove-unenc): Remove legacy field.
    old_client_secret = None
    if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
        old_client_secret = client_secret

    return OAuthApplication.create(
        organization=org,
        name=name,
        application_uri=application_uri,
        redirect_uri=redirect_uri,
        client_secret=old_client_secret,
        secure_client_secret=DecryptedValue(client_secret),
        **kwargs)
示例#10
0
def create_build_trigger(repo, service_name, auth_token, user, pull_robot=None, config=None):
    service = BuildTriggerService.get(name=service_name)

    # TODO(remove-unenc): Remove legacy field.
    old_auth_token = None
    if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
        old_auth_token = auth_token

    secure_auth_token = DecryptedValue(auth_token) if auth_token else None
    trigger = RepositoryBuildTrigger.create(
        repository=repo,
        service=service,
        auth_token=old_auth_token,
        secure_auth_token=secure_auth_token,
        connected_user=user,
        pull_robot=pull_robot,
        config=json.dumps(config or {}),
    )
    return trigger
示例#11
0
    def post(self, namespace_name, repo_name, trigger_uuid):
        """
        Activate the specified build trigger.
        """
        trigger = get_trigger(trigger_uuid)
        handler = BuildTriggerHandler.get_handler(trigger)
        if handler.is_active():
            raise InvalidRequest("Trigger config is not sufficient for activation.")

        user_permission = UserAdminPermission(trigger.connected_user.username)
        if user_permission.can():
            # Update the pull robot (if any).
            pull_robot_name = request.get_json().get("pull_robot", None)
            if pull_robot_name:
                try:
                    pull_robot = model.user.lookup_robot(pull_robot_name)
                except model.InvalidRobotException:
                    raise NotFound()

                # Make sure the user has administer permissions for the robot's namespace.
                (robot_namespace, _) = parse_robot_username(pull_robot_name)
                if not AdministerOrganizationPermission(robot_namespace).can():
                    raise Unauthorized()

                # Make sure the namespace matches that of the trigger.
                if robot_namespace != namespace_name:
                    raise Unauthorized()

                # Set the pull robot.
                trigger.pull_robot = pull_robot

            # Update the config.
            new_config_dict = request.get_json()["config"]

            write_token_name = "Build Trigger: %s" % trigger.service.name
            write_token = model.token.create_delegate_token(
                namespace_name, repo_name, write_token_name, "write"
            )

            try:
                path = url_for("webhooks.build_trigger_webhook", trigger_uuid=trigger.uuid)
                authed_url = _prepare_webhook_url(
                    app.config["PREFERRED_URL_SCHEME"],
                    "$token",
                    write_token.get_code(),
                    app.config["SERVER_HOSTNAME"],
                    path,
                )

                handler = BuildTriggerHandler.get_handler(trigger, new_config_dict)
                final_config, private_config = handler.activate(authed_url)

                if "private_key" in private_config:
                    trigger.secure_private_key = DecryptedValue(private_config["private_key"])

            except TriggerException as exc:
                write_token.delete_instance()
                raise request_error(message=exc.message)

            # Save the updated config.
            update_build_trigger(trigger, final_config, write_token=write_token)

            # Log the trigger setup.
            repo = model.repository.get_repository(namespace_name, repo_name)
            log_action(
                "setup_repo_trigger",
                namespace_name,
                {
                    "repo": repo_name,
                    "namespace": namespace_name,
                    "trigger_id": trigger.uuid,
                    "service": trigger.service.name,
                    "pull_robot": trigger.pull_robot.username if trigger.pull_robot else None,
                    "config": final_config,
                },
                repo=repo,
            )

            return trigger_view(trigger, can_admin=True)
        else:
            raise Unauthorized()
示例#12
0
def _decrypted(value):
    if value is None:
        return None

    assert isinstance(value, basestring)
    return DecryptedValue(value)
示例#13
0
def reset_client_secret(application):
    client_secret = random_string_generator(length=40)()
    application.secure_client_secret = DecryptedValue(client_secret)
    application.save()
    return application
示例#14
0
文件: trigger.py 项目: xzwupeng/quay
  def post(self, namespace_name, repo_name, trigger_uuid):
    """ Activate the specified build trigger. """
    trigger = get_trigger(trigger_uuid)
    handler = BuildTriggerHandler.get_handler(trigger)
    if handler.is_active():
      raise InvalidRequest('Trigger config is not sufficient for activation.')

    user_permission = UserAdminPermission(trigger.connected_user.username)
    if user_permission.can():
      # Update the pull robot (if any).
      pull_robot_name = request.get_json().get('pull_robot', None)
      if pull_robot_name:
        try:
          pull_robot = model.user.lookup_robot(pull_robot_name)
        except model.InvalidRobotException:
          raise NotFound()

        # Make sure the user has administer permissions for the robot's namespace.
        (robot_namespace, _) = parse_robot_username(pull_robot_name)
        if not AdministerOrganizationPermission(robot_namespace).can():
          raise Unauthorized()

        # Make sure the namespace matches that of the trigger.
        if robot_namespace != namespace_name:
          raise Unauthorized()

        # Set the pull robot.
        trigger.pull_robot = pull_robot

      # Update the config.
      new_config_dict = request.get_json()['config']

      write_token_name = 'Build Trigger: %s' % trigger.service.name
      write_token = model.token.create_delegate_token(namespace_name, repo_name, write_token_name,
                                                      'write')

      try:
        path = url_for('webhooks.build_trigger_webhook', trigger_uuid=trigger.uuid)
        authed_url = _prepare_webhook_url(app.config['PREFERRED_URL_SCHEME'],
                                          '$token', write_token.get_code(),
                                          app.config['SERVER_HOSTNAME'], path)

        handler = BuildTriggerHandler.get_handler(trigger, new_config_dict)
        final_config, private_config = handler.activate(authed_url)

        if 'private_key' in private_config:
          trigger.secure_private_key = DecryptedValue(private_config['private_key'])

          # TODO(remove-unenc): Remove legacy field.
          if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
            trigger.private_key = private_config['private_key']

      except TriggerException as exc:
        write_token.delete_instance()
        raise request_error(message=exc.message)

      # Save the updated config.
      update_build_trigger(trigger, final_config, write_token=write_token)

      # Log the trigger setup.
      repo = model.repository.get_repository(namespace_name, repo_name)
      log_action('setup_repo_trigger', namespace_name,
                 {'repo': repo_name, 'namespace': namespace_name,
                  'trigger_id': trigger.uuid, 'service': trigger.service.name,
                  'pull_robot': trigger.pull_robot.username if trigger.pull_robot else None,
                  'config': final_config},
                 repo=repo)

      return trigger_view(trigger, can_admin=True)
    else:
      raise Unauthorized()
def upgrade(op, tables, tester):
    from app import app

    logger.info("Migrating to external_reference from existing columns")
    op.add_column("repomirrorconfig", sa.Column("external_reference", sa.Text(), nullable=True))

    logger.info("Reencrypting existing columns")
    if app.config.get("SETUP_COMPLETE", False) and not tester.is_testing():
        old_key_encrypter = FieldEncrypter(app.config.get("SECRET_KEY"))

        starting_id = 0
        has_additional = True
        while has_additional:
            has_additional = False

            query = RepoMirrorConfig.select().where(RepoMirrorConfig.id >= starting_id).limit(10)
            for row in query:
                starting_id = max(starting_id, row.id + 1)
                has_additional = True
                logger.debug("Re-encrypting information for row %s", row.id)

                has_changes = False
                try:
                    if row.external_registry_username:
                        row.external_registry_username.decrypt()
                except DecryptionFailureException:
                    # Encrypted using the older SECRET_KEY. Migrate it.
                    decrypted = row.external_registry_username.decrypt(old_key_encrypter)
                    row.external_registry_username = DecryptedValue(decrypted)
                    has_changes = True

                try:
                    if row.external_registry_password:
                        row.external_registry_password.decrypt()
                except DecryptionFailureException:
                    # Encrypted using the older SECRET_KEY. Migrate it.
                    decrypted = row.external_registry_password.decrypt(old_key_encrypter)
                    row.external_registry_password = DecryptedValue(decrypted)
                    has_changes = True

                if has_changes:
                    logger.debug("Saving re-encrypted information for row %s", row.id)
                    row.save()

    if app.config.get("SETUP_COMPLETE", False) or tester.is_testing():
        for repo_mirror in _iterate(
            RepoMirrorConfig, (RepoMirrorConfig.external_reference >> None)
        ):
            repo = "%s/%s/%s" % (
                repo_mirror.external_registry,
                repo_mirror.external_namespace,
                repo_mirror.external_repository,
            )
            logger.info("migrating %s" % repo)
            repo_mirror.external_reference = repo
            repo_mirror.save()

    op.drop_column("repomirrorconfig", "external_registry")
    op.drop_column("repomirrorconfig", "external_namespace")
    op.drop_column("repomirrorconfig", "external_repository")

    op.alter_column(
        "repomirrorconfig", "external_reference", nullable=False, existing_type=sa.Text()
    )

    tester.populate_column("repomirrorconfig", "external_reference", tester.TestDataType.String)