Skip to content

Commit 4ce323f

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add separated CA cert for etcd and front-proxy"
2 parents 20413d0 + 16344a5 commit 4ce323f

File tree

20 files changed

+199
-52
lines changed

20 files changed

+199
-52
lines changed

api-ref/source/certificates.inc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ Generates and show CA certificates for bay/cluster.
99
Show details about the CA certificate for a bay/cluster
1010
=======================================================
1111

12-
.. rest_method:: GET /v1/certificates/{bay_uuid/cluster_uuid}
12+
.. rest_method:: GET /v1/certificates/{cluster_ident}?ca_cert_type={ca_cert_type}
1313

14-
Show CA certificate details that are associated with the created bay/cluster.
14+
Show CA certificate details that are associated with the created bay/cluster based on the
15+
given CA certificate type.
1516

1617
Response Codes
1718
--------------
@@ -30,7 +31,8 @@ Request
3031

3132
.. rest_parameters:: parameters.yaml
3233

33-
- bay_uuid: bay_id
34+
- cluster_ident: cluster_ident
35+
- ca_cert_type: ca_cert_type
3436

3537
.. note::
3638

api-ref/source/parameters.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ baymodel_ident:
2020
in: path
2121
required: true
2222
type: string
23+
ca_cert_type:
24+
type: string
25+
in: path
26+
required: false
27+
description: |
28+
The CA certificate type. For Kubernetes, it could be kubelet, etcd or front-proxy.
2329
cluster_ident:
2430
type: string
2531
in: path

magnum/api/controllers/v1/bay.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ def internal_attrs():
276276
'/master_addresses', '/stack_id',
277277
'/ca_cert_ref', '/magnum_cert_ref',
278278
'/trust_id', '/trustee_user_name',
279-
'/trustee_password', '/trustee_user_id']
279+
'/trustee_password', '/trustee_user_id',
280+
'/etcd_ca_cert_ref', '/front_proxy_ca_cert_ref']
280281
return types.JsonPatchType.internal_attrs() + internal_attrs
281282

282283

magnum/api/controllers/v1/certificate.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ def _set_cluster_uuid(self, value):
8888
pem = wtypes.StringType()
8989
""""The Signed Certificate"""
9090

91+
ca_cert_type = wtypes.StringType()
92+
""""The CA Certificate type the CSR will be signed by"""
93+
9194
def __init__(self, **kwargs):
9295
super(Certificate, self).__init__()
9396

@@ -113,7 +116,7 @@ def get_cluster(self):
113116
def _convert_with_links(certificate, url, expand=True):
114117
if not expand:
115118
certificate.unset_fields_except(['bay_uuid', 'cluster_uuid',
116-
'csr', 'pem'])
119+
'csr', 'pem', 'ca_cert_type'])
117120

118121
certificate.links = [link.Link.make_link('self', url,
119122
'certificates',
@@ -135,7 +138,8 @@ def sample(cls, expand=True):
135138
sample = cls(bay_uuid='7ae81bb3-dec3-4289-8d6c-da80bd8001ae',
136139
cluster_uuid='7ae81bb3-dec3-4289-8d6c-da80bd8001ae',
137140
created_at=timeutils.utcnow(),
138-
csr='AAA....AAA')
141+
csr='AAA....AAA',
142+
ca_cert_type='kubernetes')
139143
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
140144

141145

@@ -149,8 +153,8 @@ def __init__(self):
149153
'detail': ['GET'],
150154
}
151155

152-
@expose.expose(Certificate, types.uuid_or_name)
153-
def get_one(self, cluster_ident):
156+
@expose.expose(Certificate, types.uuid_or_name, wtypes.text)
157+
def get_one(self, cluster_ident, ca_cert_type=None):
154158
"""Retrieve CA information about the given cluster.
155159
156160
:param cluster_ident: UUID of a cluster or
@@ -160,7 +164,8 @@ def get_one(self, cluster_ident):
160164
cluster = api_utils.get_resource('Cluster', cluster_ident)
161165
policy.enforce(context, 'certificate:get', cluster.as_dict(),
162166
action='certificate:get')
163-
certificate = pecan.request.rpcapi.get_ca_certificate(cluster)
167+
certificate = pecan.request.rpcapi.get_ca_certificate(cluster,
168+
ca_cert_type)
164169
return Certificate.convert_with_links(certificate)
165170

166171
@expose.expose(Certificate, body=Certificate, status_code=201)

magnum/api/controllers/v1/cluster.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@ def internal_attrs():
294294
'/master_addresses', '/stack_id',
295295
'/ca_cert_ref', '/magnum_cert_ref',
296296
'/trust_id', '/trustee_user_name',
297-
'/trustee_password', '/trustee_user_id']
297+
'/trustee_password', '/trustee_user_id',
298+
'/etcd_ca_cert_ref', '/front_proxy_ca_cert_ref']
298299
return types.JsonPatchType.internal_attrs() + internal_attrs
299300

300301

magnum/conductor/api.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ def sign_certificate(self, cluster, certificate):
126126
return self._call('sign_certificate', cluster=cluster,
127127
certificate=certificate)
128128

129-
def get_ca_certificate(self, cluster):
130-
return self._call('get_ca_certificate', cluster=cluster)
129+
def get_ca_certificate(self, cluster, ca_cert_type=None):
130+
return self._call('get_ca_certificate', cluster=cluster,
131+
ca_cert_type=ca_cert_type)
131132

132133
def rotate_ca_certificate(self, cluster):
133134
return self._call('rotate_ca_certificate', cluster=cluster)

magnum/conductor/handlers/ca_conductor.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,25 @@ def __init__(self):
4343

4444
def sign_certificate(self, context, cluster, certificate):
4545
LOG.debug("Creating self signed x509 certificate")
46+
try:
47+
ca_cert_type = certificate.ca_cert_type
48+
except Exception as e:
49+
LOG.debug("There is no CA cert type specified for the CSR")
50+
ca_cert_type = "kubernetes"
51+
4652
signed_cert = cert_manager.sign_node_certificate(cluster,
4753
certificate.csr,
54+
ca_cert_type,
4855
context=context)
4956
if six.PY3 and isinstance(signed_cert, six.binary_type):
5057
certificate.pem = signed_cert.decode()
5158
else:
5259
certificate.pem = signed_cert
5360
return certificate
5461

55-
def get_ca_certificate(self, context, cluster):
56-
ca_cert = cert_manager.get_cluster_ca_certificate(cluster,
57-
context=context)
62+
def get_ca_certificate(self, context, cluster, ca_cert_type=None):
63+
ca_cert = cert_manager.get_cluster_ca_certificate(
64+
cluster, context=context, ca_cert_type=ca_cert_type)
5865
certificate = objects.Certificate.from_object_cluster(cluster)
5966
if six.PY3 and isinstance(ca_cert.get_certificate(), six.binary_type):
6067
certificate.pem = ca_cert.get_certificate().decode()

magnum/conductor/handlers/common/cert_manager.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,34 @@ def generate_certificates_to_cluster(cluster, context=None):
110110

111111
ca_cert_ref, ca_cert, ca_password = _generate_ca_cert(issuer_name,
112112
context=context)
113+
etcd_ca_cert_ref, _, _ = _generate_ca_cert(issuer_name,
114+
context=context)
115+
fp_ca_cert_ref, _, _ = _generate_ca_cert(issuer_name,
116+
context=context)
113117
magnum_cert_ref = _generate_client_cert(issuer_name,
114118
ca_cert,
115119
ca_password,
116120
context=context)
117121

118122
cluster.ca_cert_ref = ca_cert_ref
119123
cluster.magnum_cert_ref = magnum_cert_ref
124+
cluster.etcd_ca_cert_ref = etcd_ca_cert_ref
125+
cluster.front_proxy_ca_cert_ref = fp_ca_cert_ref
120126
except Exception:
121127
LOG.exception('Failed to generate certificates for Cluster: %s',
122128
cluster.uuid)
123129
raise exception.CertificatesToClusterFailed(cluster_uuid=cluster.uuid)
124130

125131

126-
def get_cluster_ca_certificate(cluster, context=None):
132+
def get_cluster_ca_certificate(cluster, context=None, ca_cert_type=None):
133+
ref = cluster.ca_cert_ref
134+
if ca_cert_type == "etcd":
135+
ref = cluster.etcd_ca_cert_ref
136+
elif ca_cert_type in ["front_proxy", "front-proxy"]:
137+
ref = cluster.front_proxy_ca_cert_ref
138+
127139
ca_cert = cert_manager.get_backend().CertManager.get_cert(
128-
cluster.ca_cert_ref,
140+
ref,
129141
resource_ref=cluster.uuid,
130142
context=context
131143
)
@@ -202,9 +214,15 @@ def create_client_files(cluster, context=None):
202214
return ca_file, key_file, cert_file
203215

204216

205-
def sign_node_certificate(cluster, csr, context=None):
217+
def sign_node_certificate(cluster, csr, ca_cert_type=None, context=None):
218+
ref = cluster.ca_cert_ref
219+
if ca_cert_type == "etcd":
220+
ref = cluster.etcd_ca_cert_ref
221+
elif ca_cert_type in ["front_proxy", "front-proxy"]:
222+
ref = cluster.front_proxy_ca_cert_ref
223+
206224
ca_cert = cert_manager.get_backend().CertManager.get_cert(
207-
cluster.ca_cert_ref,
225+
ref,
208226
resource_ref=cluster.uuid,
209227
context=context
210228
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2020 Catalyst IT LTD. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
"""separated CA cert for etcd and front-proxy
16+
17+
Revision ID: 7da8489d6a68
18+
Revises: f1d8b0ab8b8d
19+
Create Date: 2020-08-19 17:18:27.634467
20+
21+
"""
22+
23+
# revision identifiers, used by Alembic.
24+
revision = '7da8489d6a68'
25+
down_revision = 'f1d8b0ab8b8d'
26+
27+
from alembic import op # noqa: E402 # noqa: E402
28+
29+
from oslo_db.sqlalchemy.types import String # noqa: E402
30+
31+
import sqlalchemy as sa # noqa: E402
32+
33+
from sqlalchemy.dialects.mysql import TEXT # noqa: E402
34+
35+
36+
def upgrade():
37+
op.add_column('cluster', sa.Column('etcd_ca_cert_ref',
38+
String(512, mysql_ndb_type=TEXT),
39+
nullable=True))
40+
op.add_column('cluster', sa.Column('front_proxy_ca_cert_ref',
41+
String(512, mysql_ndb_type=TEXT),
42+
nullable=True))

magnum/db/sqlalchemy/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ class Cluster(Base):
145145
# so, we use 512 chars to get some buffer.
146146
ca_cert_ref = Column(String(512, mysql_ndb_type=mysql_TEXT))
147147
magnum_cert_ref = Column(String(512, mysql_ndb_type=mysql_TEXT))
148+
etcd_ca_cert_ref = Column(String(512, mysql_ndb_type=mysql_TEXT))
149+
front_proxy_ca_cert_ref = Column(String(512, mysql_ndb_type=mysql_TEXT))
148150
fixed_network = Column(String(255, mysql_ndb_type=TINYTEXT))
149151
fixed_subnet = Column(String(255, mysql_ndb_type=TINYTEXT))
150152
floating_ip_enabled = Column(Boolean, default=True)

0 commit comments

Comments
 (0)