Add function to recreate ec2 credential
At the moment, we can view the credentials of ec2 in Horizon. But we can not delete or update it. When information of access key and secret key were leaked out, it would be nice if we can regenerate a credentials via not only CLI but also Horizon. Thus we need to provide a function user can change ec2 credentials when user want to do it. Change-Id: Ibaebad73eb9a869564bd7d52e2f6b69a503a60c3 Closes-Bug: #1519764
This commit is contained in:
parent
8cade6356e
commit
a9e9d715bb
@ -715,6 +715,10 @@ def get_user_ec2_credentials(request, user_id, access_token):
|
||||
return ec2_manager(request).get(user_id, access_token)
|
||||
|
||||
|
||||
def delete_user_ec2_credentials(request, user_id, access_token):
|
||||
return ec2_manager(request).delete(user_id, access_token)
|
||||
|
||||
|
||||
def keystone_can_edit_domain():
|
||||
backend_settings = getattr(settings, "OPENSTACK_KEYSTONE_BACKEND", {})
|
||||
can_edit_domain = backend_settings.get('can_edit_domain', True)
|
||||
|
@ -0,0 +1,68 @@
|
||||
# Copyright 2016 NEC Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
|
||||
def get_ec2_credentials(request):
|
||||
if not policy.check((("identity", "identity:ec2_list_credentials"),),
|
||||
request):
|
||||
return None
|
||||
|
||||
project_id = request.user.project_id
|
||||
all_keys = api.keystone.list_ec2_credentials(request,
|
||||
request.user.id)
|
||||
keys = [x for x in all_keys if x.tenant_id == project_id]
|
||||
if not keys:
|
||||
return None
|
||||
return {'ec2_access_key': keys[0].access,
|
||||
'ec2_secret_key': keys[0].secret}
|
||||
|
||||
|
||||
class RecreateCredentials(forms.SelfHandlingForm):
|
||||
|
||||
def handle(self, request, context):
|
||||
try:
|
||||
credential = get_ec2_credentials(request)
|
||||
if credential:
|
||||
api.keystone.delete_user_ec2_credentials(
|
||||
request,
|
||||
request.user.id,
|
||||
credential['ec2_access_key'])
|
||||
except Exception:
|
||||
exceptions.handle(
|
||||
request, _('Unable to recreate ec2 credentials. '
|
||||
'Failed to delete ec2 credentials.'))
|
||||
return False
|
||||
|
||||
try:
|
||||
api.keystone.create_ec2_credentials(
|
||||
request,
|
||||
request.user.id,
|
||||
request.user.project_id)
|
||||
message = _('Successfully recreated ec2 credentials.')
|
||||
messages.success(request, message)
|
||||
return True
|
||||
except Exception:
|
||||
exceptions.handle(
|
||||
request, _('Unable to recreate ec2 credentials. '
|
||||
'Failed to create ec2 credentials.'))
|
||||
return False
|
@ -19,6 +19,9 @@ from openstack_auth import utils
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.access_and_security.api_access \
|
||||
import forms as project_forms
|
||||
from openstack_dashboard import policy
|
||||
|
||||
|
||||
def pretty_service_names(name):
|
||||
@ -69,6 +72,29 @@ class ViewCredentials(tables.LinkAction):
|
||||
url = "horizon:project:access_and_security:api_access:view_credentials"
|
||||
|
||||
|
||||
class RecreateCredentials(tables.LinkAction):
|
||||
name = "recreate_credentials"
|
||||
verbose_name = _("Recreate EC2 Credentials")
|
||||
classes = ("ajax-modal", "btn-danger")
|
||||
icon = "refresh"
|
||||
url = \
|
||||
"horizon:project:access_and_security:api_access:recreate_credentials"
|
||||
policy_rules = (("compute", "compute_extension:certificates"))
|
||||
|
||||
def allowed(self, request, datum=None):
|
||||
try:
|
||||
target = {"target.credential.user_id": request.user.id}
|
||||
if (api.base.is_service_enabled(request, 'ec2') and
|
||||
project_forms.get_ec2_credentials(request) and
|
||||
policy.check((("identity", "identity:ec2_create_credential"),
|
||||
("identity", "identity:ec2_delete_credential")),
|
||||
request, target=target)):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
class EndpointsTable(tables.DataTable):
|
||||
api_name = tables.Column('type',
|
||||
verbose_name=_("Service"),
|
||||
@ -81,4 +107,4 @@ class EndpointsTable(tables.DataTable):
|
||||
verbose_name = _("API Endpoints")
|
||||
multi_select = False
|
||||
table_actions = (DownloadOpenRCv2, DownloadOpenRC, DownloadEC2,
|
||||
ViewCredentials)
|
||||
ViewCredentials, RecreateCredentials)
|
||||
|
@ -22,11 +22,13 @@ from openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:access_and_security:index')
|
||||
API_URL = "horizon:project:access_and_security:api_access"
|
||||
EC2_URL = reverse(API_URL + ":ec2")
|
||||
OPENRC_URL = reverse(API_URL + ":openrc")
|
||||
OPENRCV2_URL = reverse(API_URL + ":openrcv2")
|
||||
CREDS_URL = reverse(API_URL + ":view_credentials")
|
||||
RECREATE_CREDS_URL = reverse(API_URL + ":recreate_credentials")
|
||||
|
||||
|
||||
class APIAccessTests(test.TestCase):
|
||||
@ -96,3 +98,40 @@ class APIAccessTests(test.TestCase):
|
||||
self.assertEqual(self.user.id, res.context['openrc_creds']['user'].id)
|
||||
self.assertEqual(certs[0].access,
|
||||
res.context['ec2_creds']['ec2_access_key'])
|
||||
|
||||
@test.create_stubs({api.keystone: ("list_ec2_credentials",
|
||||
"create_ec2_credentials",
|
||||
"delete_user_ec2_credentials",)})
|
||||
def _test_recreate_user_credentials(self, exists_credentials=True):
|
||||
old_creds = self.ec2.list() if exists_credentials else []
|
||||
new_creds = self.ec2.first()
|
||||
api.keystone.list_ec2_credentials(
|
||||
IsA(HttpRequest),
|
||||
self.user.id).AndReturn(old_creds)
|
||||
if exists_credentials:
|
||||
api.keystone.delete_user_ec2_credentials(
|
||||
IsA(HttpRequest),
|
||||
self.user.id,
|
||||
old_creds[0].access).AndReturn([])
|
||||
api.keystone.create_ec2_credentials(
|
||||
IsA(HttpRequest),
|
||||
self.user.id,
|
||||
self.tenant.id).AndReturn(new_creds)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res_get = self.client.get(RECREATE_CREDS_URL)
|
||||
self.assertEqual(res_get.status_code, 200)
|
||||
credentials = \
|
||||
'project/access_and_security/api_access/recreate_credentials.html'
|
||||
self.assertTemplateUsed(res_get, credentials)
|
||||
|
||||
res_post = self.client.post(RECREATE_CREDS_URL)
|
||||
self.assertNoFormErrors(res_post)
|
||||
self.assertRedirectsNoFollow(res_post, INDEX_URL)
|
||||
|
||||
def test_recreate_user_credentials(self):
|
||||
self._test_recreate_user_credentials()
|
||||
|
||||
def test_recreate_user_credentials_with_no_existing_creds(self):
|
||||
self._test_recreate_user_credentials(exists_credentials=False)
|
||||
|
@ -29,5 +29,7 @@ urlpatterns = patterns(
|
||||
url(r'^openrc/$', views.download_rc_file, name='openrc'),
|
||||
url(r'^openrcv2/$', views.download_rc_file_v2, name='openrcv2'),
|
||||
url(r'^view_credentials/$', views.CredentialsView.as_view(),
|
||||
name='view_credentials')
|
||||
name='view_credentials'),
|
||||
url(r'^recreate_ec2_credentials/$',
|
||||
views.RecreateCredentialsView.as_view(), name='recreate_credentials'),
|
||||
)
|
||||
|
@ -17,6 +17,7 @@ import logging
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django import http
|
||||
from django import shortcuts
|
||||
from django.template.loader import render_to_string
|
||||
@ -30,7 +31,8 @@ from horizon import messages
|
||||
from horizon import views
|
||||
|
||||
from openstack_dashboard import api
|
||||
|
||||
from openstack_dashboard.dashboards.project.access_and_security.api_access \
|
||||
import forms as project_forms
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -167,3 +169,15 @@ class CredentialsView(forms.ModalFormMixin, views.HorizonTemplateView):
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to get EC2 credentials'))
|
||||
return context
|
||||
|
||||
|
||||
class RecreateCredentialsView(forms.ModalFormView):
|
||||
form_class = project_forms.RecreateCredentials
|
||||
form_id = "recreate_credentials"
|
||||
modal_header = _("Recreate EC2 Credentials")
|
||||
template_name = \
|
||||
'project/access_and_security/api_access/recreate_credentials.html'
|
||||
submit_label = _("Recreate EC2 Credentials")
|
||||
submit_url = reverse_lazy(
|
||||
"horizon:project:access_and_security:api_access:recreate_credentials")
|
||||
success_url = reverse_lazy('horizon:project:access_and_security:index')
|
||||
|
@ -0,0 +1,6 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block modal-body %}
|
||||
{% trans "This action cannot be undone. Current EC2 credentials will be deleted and not recoverable." %}
|
||||
{% endblock %}
|
@ -0,0 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Recreate EC2 Credentials" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/access_and_security/api_access/_recreate_credentials.html' %}
|
||||
{% endblock %}
|
@ -46,6 +46,7 @@ $icon-swap: (
|
||||
plus: 'plus',
|
||||
question-circle: 'help-circle',
|
||||
random: 'shuffle',
|
||||
refresh: 'refresh',
|
||||
remove: 'close',
|
||||
save: 'floppy',
|
||||
search: 'magnify',
|
||||
|
Loading…
Reference in New Issue
Block a user