From 2574854a283c9448c4d442bb2a41ce7a1ad6298a Mon Sep 17 00:00:00 2001 From: TommyLike Date: Thu, 27 Jul 2023 09:19:57 +0800 Subject: [PATCH] Support migrate eur keys to signatrust 1. Extend name and descrption length to 210/200 characters --- app/src/pages/listShow/CreatePgp.vue | 6 +- app/src/pages/listShow/CreateX509.vue | 6 +- app/src/pages/listShow/ImportPgp.vue | 6 +- app/src/pages/listShow/ImportX509.vue | 6 +- config/client.toml | 8 ++ ...0230727020628_extend-datakey-name.down.sql | 2 + .../20230727020628_extend-datakey-name.up.sql | 2 + .../handler/control/model/datakey/dto.rs | 20 ++-- tools/migrate-pgp-local-keys/README.md | 44 ++++++++ tools/migrate-pgp-local-keys/migrate.py | 101 ++++++++++++++++++ tools/migrate-pgp-local-keys/requirements.txt | 2 + 11 files changed, 181 insertions(+), 22 deletions(-) create mode 100644 migrations/20230727020628_extend-datakey-name.down.sql create mode 100644 migrations/20230727020628_extend-datakey-name.up.sql create mode 100644 tools/migrate-pgp-local-keys/README.md create mode 100644 tools/migrate-pgp-local-keys/migrate.py create mode 100644 tools/migrate-pgp-local-keys/requirements.txt diff --git a/app/src/pages/listShow/CreatePgp.vue b/app/src/pages/listShow/CreatePgp.vue index 3ca73bc..d2d0a76 100644 --- a/app/src/pages/listShow/CreatePgp.vue +++ b/app/src/pages/listShow/CreatePgp.vue @@ -218,10 +218,10 @@ const isName = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{4,20}$/; + const reg = /^[a-zA-Z0-9-]{4,256}$/; const name = reg.test(value); if (!name) { - callback(new Error("The value contains 4 to 20 English characters")); + callback(new Error("The value contains 4 to 256 English characters")); } else { const param = ref({ name: value, @@ -238,7 +238,7 @@ const isDesc = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-\s]{1,100}$/; + const reg = /^[a-zA-Z0-9-\s]{1,200}$/; const desc = reg.test(value); if (!desc) { callback(new Error("The value contains a maximum of 100 English characters")); diff --git a/app/src/pages/listShow/CreateX509.vue b/app/src/pages/listShow/CreateX509.vue index 4f151cb..3f46bee 100644 --- a/app/src/pages/listShow/CreateX509.vue +++ b/app/src/pages/listShow/CreateX509.vue @@ -309,10 +309,10 @@ const isName = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{4,20}$/; + const reg = /^[a-zA-Z0-9-]{4,256}$/; const name = reg.test(value); if (!name) { - callback(new Error('The value contains 4 to 20 English characters')); + callback(new Error('The value contains 4 to 256 English characters')); } else { const param = ref({ name: value, @@ -329,7 +329,7 @@ const isDesc = (rule: any, value: any, callback: any) => { if (!value) { callback(console.log('avc')); } else { - const reg = /^[a-zA-Z0-9-\s]{1,100}$/; + const reg = /^[a-zA-Z0-9-\s]{1,200}$/; const desc = reg.test(value); if (!desc) { callback( diff --git a/app/src/pages/listShow/ImportPgp.vue b/app/src/pages/listShow/ImportPgp.vue index dc726b1..e09f00c 100644 --- a/app/src/pages/listShow/ImportPgp.vue +++ b/app/src/pages/listShow/ImportPgp.vue @@ -218,10 +218,10 @@ const isName = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{4,20}$/; + const reg = /^[a-zA-Z0-9-]{4,256}$/; const name = reg.test(value); if (!name) { - callback(new Error("The value contains 4 to 20 English characters")); + callback(new Error("The value contains 4 to 256 English characters")); } else { const param = ref({ name: value, @@ -261,7 +261,7 @@ const isDesc = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{1,100}$/; + const reg = /^[a-zA-Z0-9-]{1,200}$/; const desc = reg.test(value); if (!desc) { callback(new Error("The value contains a maximum of 100 English characters")); diff --git a/app/src/pages/listShow/ImportX509.vue b/app/src/pages/listShow/ImportX509.vue index da0da08..5504490 100644 --- a/app/src/pages/listShow/ImportX509.vue +++ b/app/src/pages/listShow/ImportX509.vue @@ -199,10 +199,10 @@ const isName = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{4,20}$/; + const reg = /^[a-zA-Z0-9-]{4,256}$/; const name = reg.test(value); if (!name) { - callback(new Error("The value contains 4 to 20 English characters")); + callback(new Error("The value contains 4 to 256 English characters")); } else { const param = ref({ name: value, @@ -219,7 +219,7 @@ const isDesc = (rule: any, value: any, callback: any) => { if (!value) { callback(); } else { - const reg = /^[a-zA-Z0-9-]{1,100}$/; + const reg = /^[a-zA-Z0-9-]{1,200}$/; const desc = reg.test(value); if (!desc) { callback(new Error("The value contains a maximum of 100 English characters")); diff --git a/config/client.toml b/config/client.toml index 55e84ec..a21e3ac 100644 --- a/config/client.toml +++ b/config/client.toml @@ -15,3 +15,11 @@ server_port = "8088" #type = "dns" #server_address = "a.svc.cluster" #server_port = "8080" +# ============================================== +# configuration to use signatrust test server +# domain_name = "signatrust-data-server.test.osinfra.cn" +# tls_cert = "/Users/tommylike/Work/codes/rust-projects/signatrust/.data/certs/client/server.crt" +# tls_key = "/Users/tommylike/Work/codes/rust-projects/signatrust/.data/certs/client/server.key" +# type = "single" +# server_address = "signatrust-data-server.test.osinfra.cn" +# server_port = "443" diff --git a/migrations/20230727020628_extend-datakey-name.down.sql b/migrations/20230727020628_extend-datakey-name.down.sql new file mode 100644 index 0000000..dbb8baf --- /dev/null +++ b/migrations/20230727020628_extend-datakey-name.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +ALTER TABLE data_key MODIFY COLUMN name VARCHAR(100); diff --git a/migrations/20230727020628_extend-datakey-name.up.sql b/migrations/20230727020628_extend-datakey-name.up.sql new file mode 100644 index 0000000..b8b065e --- /dev/null +++ b/migrations/20230727020628_extend-datakey-name.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +ALTER TABLE data_key MODIFY COLUMN name VARCHAR(256); diff --git a/src/presentation/handler/control/model/datakey/dto.rs b/src/presentation/handler/control/model/datakey/dto.rs index fb260ca..1574f34 100644 --- a/src/presentation/handler/control/model/datakey/dto.rs +++ b/src/presentation/handler/control/model/datakey/dto.rs @@ -59,8 +59,8 @@ impl TryFrom for CRLContent { #[derive(Deserialize, IntoParams, Validate, ToSchema)] pub struct NameIdenticalQuery { - /// Key Name, should be identical, length between 4 and 20, not contains any colon symbol. - #[validate(length(min = 4, max = 20), custom = "validate_invalid_character")] + /// Key Name, should be identical, length between 4 and 256, not contains any colon symbol. + #[validate(length(min = 4, max = 256), custom = "validate_invalid_character")] pub name: String, } @@ -74,11 +74,11 @@ pub struct ListKeyQuery { #[derive(Debug, Validate, Deserialize, ToSchema)] pub struct CreateDataKeyDTO { - /// Key Name, should be identical, length between 4 and 20, not contains any colon symbol. - #[validate(length(min = 4, max = 20), custom = "validate_invalid_character")] + /// Key Name, should be identical, length between 4 and 256, not contains any colon symbol. + #[validate(length(min = 4, max = 256), custom = "validate_invalid_character")] pub name: String, - /// Description, length between 0 and 100 - #[validate(length(min = 0, max = 100))] + /// Description, length between 0 and 200 + #[validate(length(min = 0, max = 200))] pub description: String, /// Attributes in map #[serde(serialize_with = "sorted_map")] @@ -94,11 +94,11 @@ pub struct CreateDataKeyDTO { #[derive(Debug, Validate, Deserialize, ToSchema)] pub struct ImportDataKeyDTO { - /// Key Name, should be identical, length between 4 and 20, not contains any colon symbol. - #[validate(length(min = 4, max = 20), custom = "validate_invalid_character")] + /// Key Name, should be identical, length between 4 and 256, not contains any colon symbol. + #[validate(length(min = 4, max = 256), custom = "validate_invalid_character")] pub name: String, - /// Description, length between 0 and 100 - #[validate(length(min = 0, max = 100))] + /// Description, length between 0 and 200 + #[validate(length(min = 0, max = 200))] pub description: String, /// Attributes in map pub attributes: HashMap, diff --git a/tools/migrate-pgp-local-keys/README.md b/tools/migrate-pgp-local-keys/README.md new file mode 100644 index 0000000..8eb822d --- /dev/null +++ b/tools/migrate-pgp-local-keys/README.md @@ -0,0 +1,44 @@ +# Process to migrate keys from EUR to Signatrust + +## Requirements +1. Python, Pip and Gpg +2. python-gnupg and requests libraries + +## Copy pgp data files from EUR to local +Get the kubeconfig and copy the whole directory by kubectl command +```shell +mkdir local-store +kubectl cp -c /:/var/lib/copr-keygen/gnupg ./local-store +``` + +## Using python docker image to run the script +we need to mount the pgp data folder as well as the python script folder +```shell +docker pull python:3.11 +# mount local_store and migrate.py folder +docker run -it --entrypoint bash -v :/app/working-dir -v :/app/data python:3.11 +``` + +## Install requirements(in Docker) +```shell +cd /app/working-dir +pip install -r requirments.txt +`` +``` + +## Migrate Keys(in Docker) +Generate the signatrust API token, user email and use it in the following command +```shell +python migrate.py https://signatrust.test.osinfra.cn/ /app/data +====================== processing 1 key: mywaaagh_admin_copr ==================== +key: mywaaagh_admin_copr already exists +key: mywaaagh_admin_copr skip creating +====================== processing 2 key: mywaaagh_admin_fish ==================== +key: mywaaagh_admin_fish already exists +key: mywaaagh_admin_fish skip creating +exit +``` +## Remove the local folder +```shell +rm -f +``` \ No newline at end of file diff --git a/tools/migrate-pgp-local-keys/migrate.py b/tools/migrate-pgp-local-keys/migrate.py new file mode 100644 index 0000000..aeeda0e --- /dev/null +++ b/tools/migrate-pgp-local-keys/migrate.py @@ -0,0 +1,101 @@ +# Script to migrate keys from GPG local store to signatrust server + +import sys +import gnupg +from datetime import datetime, timezone +import requests + + +class KeyMigration: + def __init__(self, signatrust_url=None, token=None, email=None, gpg_home=None): + self.headers = { + "Authorization": token, + "Content-Type": "application/json" + } + self.signatrust_url = signatrust_url.strip("/") + self.gpg = gnupg.GPG(gnupghome=gpg_home) + self.email = email + + def _check_name_exists(self, name): + response = requests.head("{}/api/v1/keys/name_identical?name={}&visibility=private".format(self.signatrust_url, name), headers=self.headers, verify=False) + if response.status_code == 200: + print("key: {} does not exist".format(name)) + return True + if response.status_code == 409: + print("key: {} already exists".format(name)) + return False + print("failed to check key name existence code {}: and response: {}".format(response.status_code, response.content)) + raise Exception("failed to determine key duplication") + + def _check_key_enabled(self, name): + response = requests.get("{}/api/v1/keys/{}".format(self.signatrust_url, name), headers=self.headers, verify=False) + if response.status_code == 200: + key_status = response.json() + return key_status["key_state"] == "enabled" + print("failed to get key status code {}: and response: {}".format(response.status_code, response.content)) + raise Exception("failed to get key") + + def _enable_key(self, name): + response = requests.post("{}/api/v1/keys/{}/actions/enable".format(self.signatrust_url, name), headers=self.headers, verify=False) + if response.status_code == 200: + print("key: {} has been successfully enabled".format(name)) + return + print("failed to enable key {}: and response: {}".format(response.status_code, response.content)) + raise Exception("failed to enable key") + + def _create_key(self, attribute): + response = requests.post("{}/api/v1/keys/import".format(self.signatrust_url), json=attribute, headers=self.headers, verify=False) + if response.status_code == 201: + print("key: {} has been successfully created".format(attribute["name"])) + return response.json()["name"] + raise Exception("failed to create key {} status {} and response {}".format(attribute["name"], response.status_code, response.content)) + + def _collect_keys_from_pgp_local_store(self): + results = [] + keys = self.gpg.list_keys(True) + for k in keys: + ids = k["uids"][0].split(" ") + key = { + "attributes": { + "digest_algorithm": "sha2_256", + "key_type": "rsa", + "key_length": k["length"], + "expire_at": "{}".format(datetime.fromtimestamp(int(k["expires"]), tz=timezone.utc)), + }, + 'name': ids[0], + 'key_type': 'pgp', + 'visibility': 'private', + 'email': ids[2].strip('<').strip('>'), + "description": "imported from EUR server", + 'create_at': "{}".format(datetime.fromtimestamp(int(k["date"]), tz=timezone.utc)), + 'expire_at': "{}".format(datetime.fromtimestamp(int(k["expires"]), tz=timezone.utc)), + 'public_key': self.gpg.export_keys(k["keyid"]), + 'private_key': self.gpg.export_keys(k["keyid"], secret=True, passphrase=""), + 'certificate': "", + } + results.append(key) + return results + + def migrate(self): + keys = self._collect_keys_from_pgp_local_store() + for i, k in enumerate(keys): + print("====================== processing {} key: {} ====================".format(i+1, k["name"])) + if len(k["name"]) > 256: + print("key: {} is too long, skip creating".format(k["name"])) + continue + if self._check_name_exists(k["name"]): + self._create_key(k) + print("key: {} has been successfully created".format(k["name"])) + else: + print("key: {} skip creating".format(k["name"])) + if not self._check_key_enabled("{}:{}".format(self.email, k["name"])): + print("key: {} is not enabled".format(k["name"])) + self._enable_key("{}:{}".format(self.email, k["name"])) + + +if __name__ == "__main__": + if len(sys.argv) != 5: + print("please use file as following: python migrate.py ") + else: + migration = KeyMigration(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) + migration.migrate() diff --git a/tools/migrate-pgp-local-keys/requirements.txt b/tools/migrate-pgp-local-keys/requirements.txt new file mode 100644 index 0000000..477fade --- /dev/null +++ b/tools/migrate-pgp-local-keys/requirements.txt @@ -0,0 +1,2 @@ +python-gnupg +requests \ No newline at end of file -- Gitee