~ubuntu-branches/ubuntu/vivid/heat/vivid

1.1.16 by Chuck Short
Import upstream version 2014.2~b3
1
#
2
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
3
#    not use this file except in compliance with the License. You may obtain
4
#    a copy of the License at
5
#
6
#         http://www.apache.org/licenses/LICENSE-2.0
7
#
8
#    Unless required by applicable law or agreed to in writing, software
9
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
#    License for the specific language governing permissions and limitations
12
#    under the License.
13
14
import six
15
16
from heat.common import exception
1.1.21 by Chuck Short
Import upstream version 2015.1~b1
17
from heat.common.i18n import _
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
18
from heat.engine import attributes
19
from heat.engine import clients
20
from heat.engine import constraints
21
from heat.engine import properties
22
from heat.engine import resource
23
from heat.openstack.common import log as logging
24
25
26
LOG = logging.getLogger(__name__)
27
28
29
class Secret(resource.Resource):
30
31
    PROPERTIES = (
32
        NAME, PAYLOAD, PAYLOAD_CONTENT_TYPE, PAYLOAD_CONTENT_ENCODING,
33
        MODE, EXPIRATION, ALGORITHM, BIT_LENGTH,
34
    ) = (
35
        'name', 'payload', 'payload_content_type', 'payload_content_encoding',
36
        'mode', 'expiration', 'algorithm', 'bit_length',
37
    )
38
39
    ATTRIBUTES = (
40
        STATUS, DECRYPTED_PAYLOAD,
41
    ) = (
42
        'status', 'decrypted_payload',
43
    )
44
45
    properties_schema = {
46
        NAME: properties.Schema(
47
            properties.Schema.STRING,
48
            _('Human readable name for the secret.'),
49
        ),
50
        PAYLOAD: properties.Schema(
51
            properties.Schema.STRING,
52
            _('The unencrypted plain text of the secret.'),
53
        ),
54
        PAYLOAD_CONTENT_TYPE: properties.Schema(
55
            properties.Schema.STRING,
56
            _('The type/format the secret data is provided in.'),
57
            constraints=[
58
                constraints.AllowedValues([
59
                    'text/plain',
60
                    'application/octet-stream',
61
                ]),
62
            ],
63
        ),
64
        PAYLOAD_CONTENT_ENCODING: properties.Schema(
65
            properties.Schema.STRING,
66
            _('The encoding format used to provide the payload data.'),
67
            default='base64',
68
            constraints=[
69
                constraints.AllowedValues([
70
                    'base64',
71
                ]),
72
            ],
73
        ),
74
        EXPIRATION: properties.Schema(
75
            properties.Schema.STRING,
76
            _('The expiration date for the secret in ISO-8601 format.'),
77
            constraints=[
78
                constraints.CustomConstraint('iso_8601'),
79
            ],
80
        ),
81
        ALGORITHM: properties.Schema(
82
            properties.Schema.STRING,
83
            _('The algorithm type used to generate the secret.'),
84
        ),
85
        BIT_LENGTH: properties.Schema(
86
            properties.Schema.NUMBER,
87
            _('The bit-length of the secret.'),
88
            constraints=[
89
                constraints.Range(
90
                    min=0,
91
                ),
92
            ],
93
        ),
94
        MODE: properties.Schema(
95
            properties.Schema.STRING,
96
            _('The type/mode of the algorithm associated with the secret '
97
              'information.'),
98
        ),
99
    }
100
101
    attributes_schema = {
102
        STATUS: attributes.Schema(
103
            _('The status of the secret.')
104
        ),
105
        DECRYPTED_PAYLOAD: attributes.Schema(
106
            _('The decrypted secret payload.')
107
        ),
108
    }
109
110
    def barbican(self):
1.1.17 by James Page
Import upstream version 2014.2~rc1
111
        return self.client('barbican')
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
112
113
    def validate(self):
114
        super(Secret, self).validate()
115
        self._validate_payload()
116
117
    def _validate_payload(self):
118
        '''Payload is optional, but requires content type if provided.'''
119
120
        payload = self.properties.get(self.PAYLOAD)
121
        content_type = self.properties.get(self.PAYLOAD_CONTENT_TYPE)
122
        if bool(payload) != bool(content_type):
123
            msg = _("'payload' and 'payload_content_type' must both be "
124
                    "provided or omitted.")
125
            raise exception.StackValidationFailed(message=msg)
126
127
    def handle_create(self):
128
        info = dict(self.properties)
1.1.21 by Chuck Short
Import upstream version 2015.1~b1
129
        secret = self.barbican().secrets.create(**info)
1.1.17 by James Page
Import upstream version 2014.2~rc1
130
        secret_ref = secret.store()
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
131
        self.resource_id_set(secret_ref)
132
        return secret_ref
133
134
    def handle_delete(self):
135
        if not self.resource_id:
136
            return
137
1.1.17 by James Page
Import upstream version 2014.2~rc1
138
        client = self.barbican()
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
139
        try:
1.1.17 by James Page
Import upstream version 2014.2~rc1
140
            client.secrets.delete(self.resource_id)
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
141
        except client.barbican_client.HTTPClientError as exc:
142
            # This is the only exception the client raises
143
            # Inspecting the message to see if it's a 'Not Found'
144
            if 'Not Found' not in six.text_type(exc):
145
                raise
146
147
    def _resolve_attribute(self, name):
1.1.21 by Chuck Short
Import upstream version 2015.1~b1
148
        secret = self.barbican().secrets.get(self.resource_id)
1.1.17 by James Page
Import upstream version 2014.2~rc1
149
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
150
        if name == self.DECRYPTED_PAYLOAD:
1.1.17 by James Page
Import upstream version 2014.2~rc1
151
            return secret.payload
1.1.16 by Chuck Short
Import upstream version 2014.2~b3
152
153
        if name == self.STATUS:
154
            return secret.status
155
156
157
def resource_mapping():
158
    return {
159
        'OS::Barbican::Secret': Secret,
160
    }
161
162
163
def available_resource_mapping():
164
    if not clients.has_client('barbican'):
165
        return {}
166
167
    return resource_mapping()