summaryrefslogtreecommitdiffstats
path: root/keystone/token/backends/kvs.py
blob: c3c3e769a281010d976a58bd3617c4e8d7a8a18e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 OpenStack LLC
#
# 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.

import copy

from keystone.common import kvs
from keystone.common import logging
from keystone import exception
from keystone.openstack.common import timeutils
from keystone import token

LOG = logging.getLogger(__name__)


class Token(kvs.Base, token.Driver):
    """kvs backend for tokens is deprecated.

    Deprecated in Havana and will be removed in Icehouse, as this backend
    is not production grade.
    """

    def __init__(self, *args, **kw):
        super(Token, self).__init__(*args, **kw)
        LOG.warn(_("kvs token backend is DEPRECATED. Use "
                   "keystone.token.backends.sql or "
                   "keystone.token.backend.memcache instead."))

    # Public interface
    def get_token(self, token_id):
        try:
            ref = self.db.get('token-%s' % token_id)
        except exception.NotFound:
            raise exception.TokenNotFound(token_id=token_id)
        now = timeutils.utcnow()
        expiry = ref['expires']
        if expiry is None:
            raise exception.TokenNotFound(token_id=token_id)
        if expiry > now:
            return copy.deepcopy(ref)
        else:
            raise exception.TokenNotFound(token_id=token_id)

    def create_token(self, token_id, data):
        data_copy = copy.deepcopy(data)
        data_copy['id'] = token_id
        if not data_copy.get('expires'):
            data_copy['expires'] = token.default_expire_time()
        if not data_copy.get('user_id'):
            data_copy['user_id'] = data_copy['user']['id']
        self.db.set('token-%s' % token_id, data_copy)
        return copy.deepcopy(data_copy)

    def delete_token(self, token_id):
        try:
            token_ref = self.get_token(token_id)
            self.db.delete('token-%s' % token_id)
            self.db.set('revoked-token-%s' % token_id, token_ref)
        except exception.NotFound:
            raise exception.TokenNotFound(token_id=token_id)

    def is_not_expired(self, now, ref):
        return not ref.get('expires') and ref.get('expires') < now

    def is_expired(self, now, ref):
        return ref.get('expires') and ref.get('expires') < now

    def trust_matches(self, trust_id, ref):
        return ref.get('trust_id') and ref['trust_id'] == trust_id

    def _list_tokens_for_trust(self, trust_id):
        tokens = []
        now = timeutils.utcnow()
        for token, ref in self.db.items():
            if not token.startswith('token-') or self.is_expired(now, ref):
                continue
            if self.trust_matches(trust_id, ref):
                tokens.append(token.split('-', 1)[1])
        return tokens

    def _list_tokens_for_user(self, user_id, tenant_id=None):
        def user_matches(user_id, ref):
            return ref.get('user') and ref['user'].get('id') == user_id

        def tenant_matches(tenant_id, ref):
            return ((tenant_id is None) or
                    (ref.get('tenant') and
                     ref['tenant'].get('id') == tenant_id))

        tokens = []
        now = timeutils.utcnow()
        for token, ref in self.db.items():
            if not token.startswith('token-') or self.is_expired(now, ref):
                continue
            else:
                if (user_matches(user_id, ref) and
                        tenant_matches(tenant_id, ref)):
                        tokens.append(token.split('-', 1)[1])
        return tokens

    def list_tokens(self, user_id, tenant_id=None, trust_id=None):
        if trust_id:
            return self._list_tokens_for_trust(trust_id)
        else:
            return self._list_tokens_for_user(user_id, tenant_id)

    def list_revoked_tokens(self):
        tokens = []
        for token, token_ref in self.db.items():
            if not token.startswith('revoked-token-'):
                continue
            record = {}
            record['id'] = token_ref['id']
            record['expires'] = token_ref['expires']
            tokens.append(record)
        return tokens

    def flush_expired_tokens(self):
        now = timeutils.utcnow()
        for token, token_ref in self.db.items():
            if self.is_expired(now, token_ref):
                self.db.delete(token)