skyline/src/stores/barbican/containers.js
xusongfu 243f459ecd fix: fix listener info in certificate
Support multiple listeners for one certificate

Change-Id: I2f1f476236fe90293f92cf980c7e1f799b271fb1
2022-06-10 15:46:13 +08:00

228 lines
6.3 KiB
JavaScript

// Copyright 2021 99cloud
//
// 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 Base from 'stores/base';
import client from 'client';
import { action } from 'mobx';
import { SecretsStore } from './secrets';
import globalListenerStore from '../octavia/listener';
export class ContainersStore extends Base {
get client() {
return client.barbican.containers;
}
get payloadClient() {
return client.barbican.secrets.payload;
}
get fetchListByLimit() {
return true;
}
get secretStore() {
// Not globalSecretsStore here
return new SecretsStore();
}
updateMarkerParams = (limit, offset) => ({
limit,
offset,
});
get mapper() {
return (data) => {
const { container_ref, algorithm } = data;
const [, uuid] = container_ref.split('/containers/');
const { domain, expiration } = algorithm ? JSON.parse(algorithm) : {};
return {
...data,
id: uuid,
domain,
expiration,
};
};
}
async requestListAllByLimit(params, limit) {
let hasNext = true;
let data = [];
while (hasNext) {
const offset = data.length || '';
// eslint-disable-next-line no-await-in-loop
const result = await this.requestListByMarker(params, limit, offset);
const items = this.getListDataFromResult(result);
data = [...data, ...items];
if (limit >= result.total || offset >= result.total) {
hasNext = false;
}
}
return data;
}
updateItem(item, listeners) {
const { container_ref } = item;
const enabledLs = listeners.filter((ls) => {
const refs = [
ls.default_tls_container_ref,
ls.client_ca_tls_container_ref,
...ls.sni_container_refs,
];
return refs.includes(container_ref);
});
if (enabledLs.length) {
item.listener = enabledLs.map((ls) => ({
id: ls.id,
name: ls.name,
lb: ls.lbIds[0],
}));
}
return item;
}
async listDidFetch(items) {
if (items.length === 0) return items;
const [secrets, listeners] = await Promise.all([
this.secretStore.fetchList({ mode: 'SERVER' }),
globalListenerStore.fetchList(),
]);
const newItems = items.map((it) => {
const { secret_refs = [] } = it;
if (secret_refs.length === 0) {
it.hidden = true;
} else {
// Filter available secrets
secret_refs.forEach((secret) => {
const { secret_ref = '' } = secret;
const [, secretId] = secret_ref.split('/secrets/');
const theSecret = secrets.find((s) => s.id === secretId);
if (theSecret) {
Object.assign(secret, { secret_info: theSecret });
Object.assign(it, {
algorithm: theSecret.algorithm,
mode: theSecret.mode,
});
} else {
it.hidden = true;
}
});
// Determine if the certificate is used in the listener
this.updateItem(it, listeners);
}
return {
...it,
};
});
return newItems.filter((it) => it.hidden !== true);
}
async detailDidFetch(item) {
const { secret_refs = [] } = item;
const [secrets, listeners] = await Promise.all([
this.secretStore.fetchList({ mode: 'SERVER' }),
globalListenerStore.fetchList(),
]);
const secretIds = [];
// Filter available secrets
secret_refs.forEach(async (secret) => {
const { secret_ref = '' } = secret;
const [, secretId] = secret_ref.split('/secrets/');
const theSecret = secrets.find((s) => s.id === secretId);
if (theSecret) {
secretIds.push(theSecret.id);
Object.assign(secret, { secret_info: theSecret });
Object.assign(item, {
algorithm: theSecret.algorithm,
mode: theSecret.mode,
});
}
});
// Determine if the certificate is used in the listener
this.updateItem(item, listeners);
// Fetch secrets payload
const payloads = await Promise.all(
secretIds.map((id) =>
this.payloadClient.list(id, {}, { headers: { Accept: 'text/plain' } })
)
);
(payloads || []).forEach((it, index) => {
secret_refs[index].secret_info.payload = it;
});
return item;
}
@action
async create(values) {
// Create Secret
const commonData = {
name: values.name,
mode: values.mode,
payload_content_type: 'text/plain',
secret_type: 'certificate',
algorithm: JSON.stringify({
domain: values.domain,
expiration: values.expiration,
}),
};
const contentData = {
...commonData,
payload: values.certificate,
};
const createSecretArr = [this.secretStore.create(contentData)];
if (values.mode === 'SERVER') {
const privateKeyData = {
...commonData,
payload: values.private_key,
};
createSecretArr.push(this.secretStore.create(privateKeyData));
}
const [content, privateKey] = await Promise.all(createSecretArr);
// Create Containers
const secretRefs = [
{
name: 'certificate',
secret_ref: content.secret_ref,
},
];
if (privateKey) {
secretRefs.push({
name: 'private_key',
secret_ref: privateKey.secret_ref,
});
}
const data = {
type: 'certificate',
name: values.name,
secret_refs: secretRefs,
};
return this.client.create(data);
}
@action
delete = async (data) => {
const { id, secret_refs = [] } = data;
await Promise.all(
secret_refs.map((it) => {
const { secret_ref = '' } = it;
const [, secretId] = secret_ref.split('/secrets/');
return this.secretStore.delete({ id: secretId });
})
);
return this.submitting(this.client.delete(id));
};
}
const globalContainersStore = new ContainersStore();
export default globalContainersStore;