ansible / galaxy-issues

This repository exists solely for the tracking of user issues with Ansible Galaxy.
20 stars 3 forks source link

OAuth Issue With Github & Bitbucket #292

Closed rbhadti94 closed 6 years ago

rbhadti94 commented 6 years ago

I've followed instructions to setup Galaxy.

  1. At the moment the server is running on IP address A.B.C.D on an AWS machine. (This is non-prod mode so everything is still in docker containers).

  2. There is an Nginx reverse proxy setup so that the Django container port 8000 is forwarded to 80. Thus the galaxy main page is accessible via http://A.B.C.D.

  3. I've added the Github Social Application. And in Github I've set the callback authorization URL to http://A.B.C.D/accounts/github/login/callback/. Is this correct for my server?

  4. When I click Login With , I see the error:

    Social Network Login Failure
    An error occurred while attempting to login via your social network account.

Tailing the logs for the django container I see the following error message in the returned url.

# When trying to login with Github
The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application

Also

I've added Bitbucket as a social application as well in the same manner as above. When I try to login with Bitbucket, it takes me to the page:

http://127.0.0.1:8000/accounts/bitbucket/login/callback/?oauth_verifier=<verifier>&oauth_token=<oauth_token>

So in both cases it seems like 127.0.0.1 is being hit. But I cannot seem to change this to my AWS machine IP - A.B.C.D in any of the configuration or settings files.

How would I go about setting up this OAuth on a cloud machine?

chouseknecht commented 6 years ago

@rbhadti94

There is some setup you need to do inside the Admin site. It's mentioned in the Contributing doc here: https://github.com/ansible/galaxy/blob/develop/CONTRIBUTING.md#connect-to-github

As far as adding BitBucket, that's not currently on our roadmap. There's a bunch of work we would need to do in the UI, the Celery tasks, and models to support BitBucket. If you have some design ideas, would be interested in hearing them. Maybe you could help us formalize a design.

danlamanna commented 6 years ago

As far as adding BitBucket, that's not currently on our roadmap. There's a bunch of work we would need to do in the UI, the Celery tasks, and models to support BitBucket. If you have some design ideas, would be interested in hearing them. Maybe you could help us formalize a design.

Does the same go for GitLab? Also are you talking only about the server-side galaxy application, or support for checking out from URLs on the ansible-galaxy cli side as well?

On Tue, Oct 10, 2017 at 13:36 PM, Chris Houseknecht notifications@github.com wrote:

@rbhadti94

There is some setup you need to do inside the Admin site. It's mentioned in the Contributing doc here: https://github.com/ansible/galaxy/blob/develop/CONTRIBUTING.md#connect-to-github

As far as adding BitBucket, that's not currently on our roadmap. There's a bunch of work we would need to do in the UI, the Celery tasks, and models to support BitBucket. If you have some design ideas, would be interested in hearing them. Maybe you could help us formalize a design.

-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/ansible/galaxy-issues/issues/292#issuecomment-335474612

gregdek commented 6 years ago

I'd say we're closer to working on GitLab than we are on Bitbucket, since GitLab has a lot more public repositories and has a model that's more similar to GitHub. The challenge is that we'll basically need to completely rework our auth setup, since assumption of GitHub auth simplifies a lot of things for us.

rbhadti94 commented 6 years ago

Hi @chouseknecht,

I've followed those instructions for my AWS machine and used my AWS machine IP, instead of localhost when registering an OAuth application on Github.

I only see localhost when I try to add Github as a social application.

To clarify, I have set this up running on an AWS machine and am accessing the Galaxy portal through my local PC. So when I click Login With Github it redirects me to http://127.0.0.1:8000/.../ (which is localhost) instead of http:///..../.

Upon examining the logs for the Django container, I can see the redirect-uri message in the URL I mentioned above.

In terms of Bitbucket, I've simply added it as a social application and can authenticate against it using OAuth (locally), there is no functionality there at the moment. You're right that the celery tasks and models will have to be modified in order to fully support this and I've looked into this. I'd be more than happy to post some design ideas if possible?

The use-case I have is mainly to do with Bitbucket and not so much Github/Gitlab unfortunately.

cutwater commented 6 years ago

@rbhadti94 can you plese share your /etc/galaxy/settings.py file, excluding any sensitive data.

rbhadti94 commented 6 years ago

Hi @cutwater,

The /etc/galaxy/settings.py file is below. This was obtained from the running django container. Before building/running the containers, I modified the settings-develop.py.j2 file to use my AWS machine. The ALLOWED_HOSTS variable below reflects this. My AWS machine IP is A.B.C.D.

import os
import sys
import djcelery

djcelery.setup_loader()

# wsgi.py will wait on a socket connection to the following services
# before attempting to launch the appliation:
WAIT_FOR = [
    {'host': 'postgres', 'port': 5432},
    {'host': 'rabbit', 'port': 5672},
    {'host': 'memcache', 'port': 11211},
    {'host': 'elastic', 'port': 9200}
]

BASE_DIR = os.path.dirname(os.path.dirname(__file__))

ADMINS = ()

SITE_ENV="DEV"
SITE_NAME="galaxy_server"
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SEND_EMAIL=False

if SITE_ENV == "DEV":
    DEBUG = True
    DEBUG_TOOLBAR_PATCH_SETTINGS = False
else:
    DEBUG = False

MAINTENANCE_MODE = False

# Add IPs that should see django-debug-toolbar
INTERNAL_IPS = ['192.168.99.100']

LOGIN_URL='/accounts/login/'
LOGIN_REDIRECT_URL='/explore'
LOGOUT_URL='/'

if SEND_EMAIL:
    EMAIL_HOST=""
    EMAIL_PORT=0
    EMAIL_HOST_USER=""
    EMAIL_HOST_PASSWORD=""
    EMAIL_USE_TLS=True
else:
    EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
    EMAIL_FILE_PATH = '/galaxy_logs/email'

AUTH_USER_MODEL = 'accounts.CustomUser'

# Settings for django-allauth
ACCOUNT_ADAPTER = 'galaxy.main.auth.AccountAdapter'
ACCOUNT_AUTHENTICATION_METHOD="username_email"
ACCOUNT_DEFAULT_HTTP_PROTOCOL="http"
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL="/accounts/profile/"
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL="/accounts/landing"
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS=1
ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_EMAIL_VERIFICATION="mandatory"
ACCOUNT_EMAIL_SUBJECT_PREFIX="Ansible Galaxy "
ACCOUNT_LOGIN_ON_VALIDATE=True
ACCOUNT_USERNAME_MIN_LENGTH=3
ACCOUNT_USERNAME_BLACKLIST=[
    'admin',
    'administrator',
    'galaxy_admin',
    'accounts',
    'account',
    'explore',
    'intro',
    'list',
    'detail',
    'roleadd',
    'imports',
    'authors'
]
ACCOUNT_PASSWORD_MIN_LENGTH=8
SOCIALACCOUNT_PROVIDERS={
    'twitter': { 'SCOPE': ['r_emailaddress'] },
    'github': { 'SCOPE': ['user:email', 'public_repo'] },
    'bitbucket': { 'SCOPE': ['user:email', 'public_repo'] },
}

SOCIALACCOUNT_AVATAR_SUPPORT=True

# Settings for celery/rabbitmq
BROKER_URL="amqp://galaxy:galaxy@rabbit:5672/galaxy"

CELERY_IMPORTS=('galaxy.main.celerytasks.tasks',)
CELERY_TRACK_STARTED=True
CELERYBEAT_SCHEDULER='djcelery.schedulers.DatabaseScheduler'

GITHUB_TASK_USERS = []

GITHUB_SERVER = "https://api.github.com"
BITBUCKET_SERVER = "https://api.bitbucket.org/1.0"

# Custom settings
GALAXY_COMMENTS_THRESHOLD=10.0

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'galaxy',
        'USER': 'galaxy',
        'PASSWORD': 'galaxy',
        'HOST': 'postgres',
        'PORT': '5432',
        'CONN_MAX_AGE': None,
    }
}

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': 'memcache:11211',
    },
    'download_count': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'main_download_count_cache',
        'TIMEOUT': None,
        'OPTIONS': {
            'MAX_ENTRIES': 100000,
            'CULL_FREQUENCY': 0
        }
    }
}

ELASTICSEARCH = {
    'hosts': ["elastic:9200"]
}

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'galaxy.main.elasticsearch_backend.ElasticsearchSearchEngine',
        'URL': ['http://elastic:9200'],
        'INDEX_NAME': 'haystack',
    },
}

HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_SAVE_EVERY_REQUEST = True

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('galaxy.api.permissions.ModelAccessPermission',),
    'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'galaxy.api.pagination.PaginationSerializer',
    'DEFAULT_FILTER_BACKENDS': (
        'galaxy.api.filters.ActiveOnlyBackend',
        'galaxy.api.filters.FieldLookupBackend',
        'rest_framework.filters.SearchFilter',
        'galaxy.api.filters.OrderByBackend',
    ),
    'PAGINATE_BY': 10,
    'PAGINATE_BY_PARAM': 'page_size',
    'MAX_PAGINATE_BY': 1000,
    'DEFAULT_THROTTLE_CLASSES': (
        'galaxy.api.throttling.RoleDownloadCountThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'download_count': '1/day',
    }
}

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'galaxy', 'templates')],
        'APP_DIRS': True,
         'OPTIONS': {
            'debug': True,
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.template.context_processors.i18n',
                'django.template.context_processors.static',
                'django.template.context_processors.request',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [SITE_NAME]
ALLOWED_HOSTS.append('ec2-A-B-C-D.compute-1.amazonaws.com')
ALLOWED_HOSTS.append('A.B.C.D')
ALLOWED_HOSTS.append('0.0.0.0')

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/New_York'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "http://media.example.com/"
MEDIA_URL = ''

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/var/www/example.com/static/"
STATIC_ROOT = '/var/lib/galaxy/public/static'

# URL prefix for static files.
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(BASE_DIR, 'galaxy', 'static'),
)

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

# Store file names by appending the MD5 hash of the file's content to the filename.
# Works with staticfiles static templating directive.
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

# Make this unique, and don't share it with anybody.
SECRET_KEY = file('/etc/galaxy/SECRET_KEY', 'rb').read().strip()

MIDDLEWARE_CLASSES = (
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'maintenance.middleware.MaintenanceMiddleware',
)

ROOT_URLCONF = 'galaxy.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'galaxy.wsgi.application'

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'debug_toolbar',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.github',
    'allauth.socialaccount.providers.google',
    'allauth.socialaccount.providers.bitbucket',
    'allauth.socialaccount.providers.twitter',
    # 'avatar',
    'bootstrapform',
    'djcelery',
    'maintenance',
    'rest_framework',
    'rest_framework.authtoken',
    'haystack',
    # our apps
    'galaxy.accounts',
    'galaxy.main',
)

if SITE_ENV == 'DEV':
    INSTALLED_APPS += (
        'autofixture',
    )

AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',
    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',
)

MAINTENANCE_FILE = '/var/lib/galaxy/.maintenance'

TRAVIS_CONFIG_URL = 'https://api.travis-ci.org/config'

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(asctime)s %(levelname)s %(module)s: %(message)s',
        },
        'simple': {
            'format': '%(levelname)s %(message)s',
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
        #'syslog':{
        #    'level':'DEBUG',
        #    'class': 'logging.handlers.SysLogHandler',
        #    'formatter': 'verbose',
        #    'facility': 'local4',
        #    'address': '/dev/log',
        #},
        'allauth_logfile': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': "/galaxy_logs/allauth.log",
            'maxBytes': 500000,
            'backupCount': 4,
            'formatter': 'verbose',
    },
        'django_logfile': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': "/galaxy_logs/django.log",
            'maxBytes': 500000,
            'backupCount': 4,
            'formatter': 'verbose',
    },
        'galaxy_logfile': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': "/galaxy_logs/galaxy.log",
            'maxBytes': 500000,
            'backupCount': 4,
            'formatter': 'verbose',
        },
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'django': {
            'handlers': ['django_logfile'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'galaxy.api': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'galaxy.accounts': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'galaxy.main': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    'allauth': {
        'handlers': ['console'],
        'level': 'DEBUG',
        'propagate': True,
        },
    }
}
rbhadti94 commented 6 years ago

@chouseknecht, @cutwater

I've fixed this now. The SQL file located at ../roles/django-role/files/update_site.sql can be modified to take the domain name or IP address of the AWS machine. (Not sure if this is good practice)

Thanks for the help. I'd be more than happy to help out with any Bitbucket plans/ideas!