Repository: opensearch-project/opensearch-build

Issue:
[META] Automate artifact signing with OpensearchSignerClient for linux
### Is your feature request related to a problem? Please describe

Signing currently is a long painstaking process. It needs to be automated to save time when releasing artifacts. We need a tool to be able to sign all artifacts - 
- opensearch
- opensearch-dashboards

### Describe the solution you'd like

Use the existing `Signer.py` class to sign the artifacts and generate ".sig" file along with ".asc" files.

### Tasks
- [x] #1382
- [x] #1383
- [x] #1385

### Acceptance Criteria
- [ ] User is able to provide the artifact directory and tool is able to sign all the artifacts in the directory
- [ ] User is able to pass the artifact path and the tool is able to sign the artifact

### Next Steps
Next steps would include to extend this process over for mac and windows


Discussion:

Resolving patch:
diff --git a/src/sign_workflow/signer.py b/src/sign_workflow/signer.py
--- a/src/sign_workflow/signer.py
+++ b/src/sign_workflow/signer.py
@@ -26,12 +26,15 @@ def __init__(self):
         self.git_repo.execute("rm config.cfg")
 
     def sign_artifact(self, artifact, basepath, signature_type):
+        if not self.is_valid_file_type(artifact):
+            logging.info(f"Skipping signing of file {artifact}")
+            return
         self.generate_signature_and_verify(artifact, basepath, signature_type)
 
     def sign_artifacts(self, artifacts, basepath, signature_type):
         for artifact in artifacts:
             if not self.is_valid_file_type(artifact):
-                logging.info(f"Skipping signing of file ${artifact}")
+                logging.info(f"Skipping signing of file {artifact}")
                 continue
             self.generate_signature_and_verify(artifact, basepath, signature_type)
 
@@ -50,8 +53,14 @@ def get_repo_url(self):
             return "https://${GITHUB_TOKEN}@github.com/opensearch-project/opensearch-signer-client.git"
         return "https://github.com/opensearch-project/opensearch-signer-client.git"
 
+    def __remove_existing_signature__(self, signature_file):
+        if os.path.exists(signature_file):
+            logging.warning(f"Removing existing signature file {signature_file}")
+            os.remove(signature_file)
+
     def sign(self, filename, signature_type):
         signature_file = filename + signature_type
+        self.__remove_existing_signature__(signature_file)
         signing_cmd = [
             "./opensearch-signer-client",
             "-i",


Test patch:
diff --git a/tests/jenkins/TestPromoteArtifacts.groovy b/tests/jenkins/TestPromoteArtifacts.groovy
--- a/tests/jenkins/TestPromoteArtifacts.groovy
+++ b/tests/jenkins/TestPromoteArtifacts.groovy
@@ -12,7 +12,6 @@ import org.junit.*
 import java.util.*
 import java.nio.file.*
 
-
 class TestPromoteArtifacts extends BuildPipelineTest {
     private Path target;
 
@@ -36,7 +35,12 @@ class TestPromoteArtifacts extends BuildPipelineTest {
         binding.setVariable('AWS_ACCOUNT_ARTIFACT', 'artifactsAccount')
         binding.setVariable('ARTIFACT_PRODUCTION_BUCKET_NAME', 'prod-bucket-name')
         binding.setVariable('WORKSPACE', 'workspace')
-        
+        binding.setVariable('GITHUB_BOT_TOKEN_NAME', 'github_bot_token_name')
+        binding.setVariable('SIGNER_CLIENT_ROLE', 'dummy_signer_client_role')
+        binding.setVariable('SIGNER_CLIENT_EXTERNAL_ID', 'signer_client_external_id')
+        binding.setVariable('SIGNER_CLIENT_UNSIGNED_BUCKET', 'signer_client_unsigned_bucket')
+        binding.setVariable('SIGNER_CLIENT_SIGNED_BUCKET', 'signer_client_signed_bucket')
+
         helper.registerAllowedMethod("git", [Map])
         helper.registerAllowedMethod("s3Download", [Map])
         helper.registerAllowedMethod("s3Upload", [Map])
@@ -51,10 +55,26 @@ class TestPromoteArtifacts extends BuildPipelineTest {
             return [{}]
         })
 
+        helper.addShMock('find workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins -type f') { script ->
+            return [stdout: "tar_dummy_artifact_1.0.0.tar.gz zip_dummy_artifact_1.1.0.zip dummy_artifact_1.1.0.dummy", exitValue: 0]
+        }
+        helper.addShMock('sha512sum tar_dummy_artifact_1.0.0.tar.gz') { script ->
+            return [stdout: "shaHashDummy_tar_dummy_artifact_1.0.0.tar.gz  workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/tar_dummy_artifact_1.0.0.tar.gz", exitValue: 0]
+        }
+        helper.addShMock('sha512sum zip_dummy_artifact_1.1.0.zip') { script ->
+            return [stdout: "shaHashDummy_zip_dummy_artifact_1.1.0.zip  workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/zip_dummy_artifact_1.1.0.zip", exitValue: 0]
+        }
+        helper.addShMock('basename workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/tar_dummy_artifact_1.0.0.tar.gz') { script ->
+            return [stdout: "tar_dummy_artifact_1.0.0.tar.gz", exitValue: 0]
+        }
+        helper.addShMock('basename workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/zip_dummy_artifact_1.1.0.zip') { script ->
+            return [stdout: "zip_dummy_artifact_1.1.0.zip", exitValue: 0]
+        }
+
         Path source = Path.of("tests/data/opensearch-build-1.1.0.yml");
         target = Path.of("artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/manifest.yml");
         Files.createDirectories(target.getParent());
-        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);    
+        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
     }
 
     @After
diff --git a/tests/jenkins/jobs/PromoteArtifacts_Jenkinsfile.txt b/tests/jenkins/jobs/PromoteArtifacts_Jenkinsfile.txt
--- a/tests/jenkins/jobs/PromoteArtifacts_Jenkinsfile.txt
+++ b/tests/jenkins/jobs/PromoteArtifacts_Jenkinsfile.txt
@@ -4,7 +4,6 @@
          PromoteArtifacts_Jenkinsfile.stage(promote, groovy.lang.Closure)
             PromoteArtifacts_Jenkinsfile.script(groovy.lang.Closure)
                PromoteArtifacts_Jenkinsfile.promoteArtifacts({manifest=tests/jenkins/data/opensearch-1.3.0.yml})
-                  promoteArtifacts.git({url=https://github.com/opensearch-project/opensearch-build.git, branch=main})
                   promoteArtifacts.legacySCM(groovy.lang.Closure)
                   promoteArtifacts.library({identifier=jenkins@20211123, retriever=null})
                   promoteArtifacts.readYaml({file=tests/jenkins/data/opensearch-1.3.0.yml})
@@ -13,7 +12,6 @@
                      promoteArtifacts.s3Download({bucket=artifact-bucket, file=workspace/artifacts, path=vars-build/1.3.0/33/x64/linux/, force=true})
                   promoteArtifacts.readYaml({file=artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/manifest.yml})
                   promoteArtifacts.withAWS({role=artifactPromotionRole, roleAccount=artifactsAccount, duration=900, roleSessionName=jenkins-session}, groovy.lang.Closure)
-                     promoteArtifacts.println(Start Core Plugin Promotion to artifects.opensearch.org Bucket)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/discovery-ec2-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/discovery-ec2-1.1.0.zip*})
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/transport-nio-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/transport-nio-1.1.0.zip*})
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/discovery-gce-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/discovery-gce-1.1.0.zip*})
@@ -34,6 +32,5 @@
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/store-smb-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/store-smb-1.1.0.zip*})
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-smartcn-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-smartcn-1.1.0.zip*})
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/repository-gcs-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/repository-gcs-1.1.0.zip*})
-                     promoteArtifacts.println(Start Tar Core/Bundle Promotion to artifacts.opensearch.org Bucket)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/core/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/dist/, includePathPattern=**/opensearch-min-1.3.0*})
-                     promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/bundle/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/dist/opensearch/, includePathPattern=**/opensearch*-1.3.0*})
+                     promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/bundle/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/dist/opensearch/, includePathPattern=**/opensearch-1.3.0*})
diff --git a/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile b/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile
--- a/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile
+++ b/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile
@@ -6,7 +6,7 @@ pipeline {
                 script {
                     promoteArtifacts(
                         manifest: 'tests/jenkins/data/opensearch-1.3.0.yml',
-                        fileActions: [createSha512()]
+                        fileActions: [createSha512Checksums(), createSignatureFiles()]
                     )
                 }
             }
diff --git a/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile.txt b/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile.txt
--- a/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile.txt
+++ b/tests/jenkins/jobs/PromoteArtifacts_actions_Jenkinsfile.txt
@@ -3,9 +3,11 @@
          PromoteArtifacts_actions_Jenkinsfile.echo(Executing on agent [label:none])
          PromoteArtifacts_actions_Jenkinsfile.stage(promote, groovy.lang.Closure)
             PromoteArtifacts_actions_Jenkinsfile.script(groovy.lang.Closure)
-               PromoteArtifacts_actions_Jenkinsfile.createSha512()
-               PromoteArtifacts_actions_Jenkinsfile.promoteArtifacts({manifest=tests/jenkins/data/opensearch-1.3.0.yml, fileActions=[groovy.lang.Closure]})
-                  promoteArtifacts.git({url=https://github.com/opensearch-project/opensearch-build.git, branch=main})
+               PromoteArtifacts_actions_Jenkinsfile.createSha512Checksums()
+               PromoteArtifacts_actions_Jenkinsfile.createSignatureFiles()
+                  createSignatureFiles.legacySCM(groovy.lang.Closure)
+                  createSignatureFiles.library({identifier=jenkins@20211123, retriever=null})
+               PromoteArtifacts_actions_Jenkinsfile.promoteArtifacts({manifest=tests/jenkins/data/opensearch-1.3.0.yml, fileActions=[groovy.lang.Closure, groovy.lang.Closure]})
                   promoteArtifacts.legacySCM(groovy.lang.Closure)
                   promoteArtifacts.library({identifier=jenkins@20211123, retriever=null})
                   promoteArtifacts.readYaml({file=tests/jenkins/data/opensearch-1.3.0.yml})
@@ -13,94 +15,79 @@
                   promoteArtifacts.withAWS({role=downloadRoleName, roleAccount=publicAccount, duration=900, roleSessionName=jenkins-session}, groovy.lang.Closure)
                      promoteArtifacts.s3Download({bucket=artifact-bucket, file=workspace/artifacts, path=vars-build/1.3.0/33/x64/linux/, force=true})
                   promoteArtifacts.readYaml({file=artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/manifest.yml})
+                  createSha512Checksums.sh({script=find workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins -type f, returnStdout=true})
+                  createSha512Checksums.echo(Creating sha for tar_dummy_artifact_1.0.0.tar.gz)
+                  createSha512Checksums.sh({script=sha512sum tar_dummy_artifact_1.0.0.tar.gz, returnStdout=true})
+                  createSha512Checksums.sh({script=basename workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/tar_dummy_artifact_1.0.0.tar.gz, returnStdout=true})
+                  createSha512Checksums.writeFile({file=tar_dummy_artifact_1.0.0.tar.gz.sha512, text=shaHashDummy_tar_dummy_artifact_1.0.0.tar.gz  tar_dummy_artifact_1.0.0.tar.gz})
+                  createSha512Checksums.echo(Creating sha for zip_dummy_artifact_1.1.0.zip)
+                  createSha512Checksums.sh({script=sha512sum zip_dummy_artifact_1.1.0.zip, returnStdout=true})
+                  createSha512Checksums.sh({script=basename workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/zip_dummy_artifact_1.1.0.zip, returnStdout=true})
+                  createSha512Checksums.writeFile({file=zip_dummy_artifact_1.1.0.zip.sha512, text=shaHashDummy_zip_dummy_artifact_1.1.0.zip  zip_dummy_artifact_1.1.0.zip})
+                  createSha512Checksums.echo(Not generating sha for dummy_artifact_1.1.0.dummy in workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins, doesn't match allowed types [.tar.gz, .zip])
+                  createSignatureFiles.signArtifacts({signatureType=.sig, artifactPath=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins})
+                     signArtifacts.fileExists(workspace/sign.sh)
+                     signArtifacts.git({url=https://github.com/opensearch-project/opensearch-build.git, branch=main})
+                     signArtifacts.fileExists(workspace/opensearch.pgp)
+                     signArtifacts.sh(curl -SL https://artifacts.opensearch.org/publickeys/opensearch.pgp -o $WORKSPACE/opensearch.pgp)
+                     signArtifacts.sh(gpg --import $WORKSPACE/opensearch.pgp)
+                     signArtifacts.usernamePassword({credentialsId=github_bot_token_name, usernameVariable=GITHUB_USER, passwordVariable=GITHUB_TOKEN})
+                     signArtifacts.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure)
+                        signArtifacts.sh(
+            #!/bin/bash
+            set +x
+            export ROLE=dummy_signer_client_role
+            export EXTERNAL_ID=signer_client_external_id
+            export UNSIGNED_BUCKET=signer_client_unsigned_bucket
+            export SIGNED_BUCKET=signer_client_signed_bucket
+
+            workspace/sign.sh workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins --sigtype=.sig --component=null --type=null
+        )
+                  promoteArtifacts.findFiles({glob=**/opensearch-min-1.3.0*.tar.gz,**/opensearch-1.3.0*.tar.gz})
+                  promoteArtifacts.getPath()
+                  createSha512Checksums.sh({script=find workspace/workspace/file/found.zip -type f, returnStdout=true})
+                  createSha512Checksums.echo(Not generating sha for bbb in workspace/workspace/file/found.zip, doesn't match allowed types [.tar.gz, .zip])
+                  createSha512Checksums.echo(Not generating sha for ccc in workspace/workspace/file/found.zip, doesn't match allowed types [.tar.gz, .zip])
+                  promoteArtifacts.findFiles({glob=**/opensearch-min-1.3.0*.tar.gz,**/opensearch-1.3.0*.tar.gz})
+                  promoteArtifacts.getPath()
+                  createSignatureFiles.signArtifacts({signatureType=.sig, artifactPath=workspace/workspace/file/found.zip})
+                     signArtifacts.fileExists(workspace/sign.sh)
+                     signArtifacts.git({url=https://github.com/opensearch-project/opensearch-build.git, branch=main})
+                     signArtifacts.fileExists(workspace/opensearch.pgp)
+                     signArtifacts.sh(curl -SL https://artifacts.opensearch.org/publickeys/opensearch.pgp -o $WORKSPACE/opensearch.pgp)
+                     signArtifacts.sh(gpg --import $WORKSPACE/opensearch.pgp)
+                     signArtifacts.usernamePassword({credentialsId=github_bot_token_name, usernameVariable=GITHUB_USER, passwordVariable=GITHUB_TOKEN})
+                     signArtifacts.withCredentials([[GITHUB_USER, GITHUB_TOKEN]], groovy.lang.Closure)
+                        signArtifacts.sh(
+            #!/bin/bash
+            set +x
+            export ROLE=dummy_signer_client_role
+            export EXTERNAL_ID=signer_client_external_id
+            export UNSIGNED_BUCKET=signer_client_unsigned_bucket
+            export SIGNED_BUCKET=signer_client_signed_bucket
+
+            workspace/sign.sh workspace/workspace/file/found.zip --sigtype=.sig --component=null --type=null
+        )
                   promoteArtifacts.withAWS({role=artifactPromotionRole, roleAccount=artifactsAccount, duration=900, roleSessionName=jenkins-session}, groovy.lang.Closure)
-                     promoteArtifacts.println(Start Core Plugin Promotion to artifects.opensearch.org Bucket)
-                     promoteArtifacts.findFiles({glob=**/discovery-ec2-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/discovery-ec2-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/discovery-ec2-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/transport-nio-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/transport-nio-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/transport-nio-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/discovery-gce-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/discovery-gce-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/discovery-gce-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-ukrainian-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-ukrainian-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-ukrainian-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/discovery-azure-classic-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/discovery-azure-classic-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/discovery-azure-classic-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-phonetic-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-phonetic-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-phonetic-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/mapper-murmur3-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/mapper-murmur3-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/mapper-murmur3-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-kuromoji-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-kuromoji-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-kuromoji-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-stempel-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-stempel-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-stempel-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/mapper-annotated-text-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/mapper-annotated-text-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/mapper-annotated-text-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/repository-hdfs-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/repository-hdfs-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/repository-hdfs-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-icu-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-icu-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-icu-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/mapper-size-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/mapper-size-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/mapper-size-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/ingest-attachment-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/ingest-attachment-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/ingest-attachment-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/repository-azure-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/repository-azure-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/repository-azure-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/repository-s3-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/repository-s3-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/repository-s3-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-nori-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-nori-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-nori-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/store-smb-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/store-smb-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/store-smb-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/analysis-smartcn-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/analysis-smartcn-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/analysis-smartcn-1.1.0.zip*})
-                     promoteArtifacts.findFiles({glob=**/repository-gcs-1.1.0.zip*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/plugins/repository-gcs-1.1.0.zip/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/core-plugins/, includePathPattern=**/repository-gcs-1.1.0.zip*})
-                     promoteArtifacts.println(Start Tar Core/Bundle Promotion to artifacts.opensearch.org Bucket)
-                     promoteArtifacts.findFiles({glob=**/opensearch-min-1.3.0*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
                      promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/core/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/builds/opensearch/dist/, includePathPattern=**/opensearch-min-1.3.0*})
-                     promoteArtifacts.findFiles({glob=**/opensearch*-1.3.0*})
-                     promoteArtifacts.getPath()
-                     createSha512.sh(sha512sum workspace/file/found.zip > workspace/file/found.zip.sha512)
-                     promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/bundle/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/dist/opensearch/, includePathPattern=**/opensearch*-1.3.0*})
+                     promoteArtifacts.s3Upload({bucket=prod-bucket-name, path=releases/bundle/opensearch/1.3.0/, workingDir=workspace/artifacts/vars-build/1.3.0/33/x64/linux/dist/opensearch/, includePathPattern=**/opensearch-1.3.0*})
diff --git a/tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz.sig b/tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz.sig
new file mode 100644
diff --git a/tests/tests_sign_workflow/test_signer.py b/tests/tests_sign_workflow/test_signer.py
--- a/tests/tests_sign_workflow/test_signer.py
+++ b/tests/tests_sign_workflow/test_signer.py
@@ -86,10 +86,40 @@ def test_signer_verify_sig(self, mock_repo):
     def test_signer_sign_asc(self, mock_repo):
         signer = Signer()
         signer.sign("/path/the-jar.jar", ".asc")
-        mock_repo.assert_has_calls([call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.asc -p pgp")])
+        mock_repo.assert_has_calls(
+            [call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.asc -p pgp")])
 
     @patch("sign_workflow.signer.GitRepository")
     def test_signer_sign_sig(self, mock_repo):
         signer = Signer()
         signer.sign("/path/the-jar.jar", ".sig")
-        mock_repo.assert_has_calls([call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.sig -p pgp")])
+        mock_repo.assert_has_calls(
+            [call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.sig -p pgp")])
+
+    @patch("sign_workflow.signer.GitRepository")
+    def test_sign_artifact_not_called(self, mock_repo):
+        signer = Signer()
+        signer.generate_signature_and_verify = MagicMock()
+        signer.sign_artifact("the-jar.notvalid", "/path", ".sig")
+        signer.generate_signature_and_verify.assert_not_called()
+
+    @patch("sign_workflow.signer.GitRepository")
+    def test_sign_artifact_called(self, mock_repo):
+        signer = Signer()
+        signer.generate_signature_and_verify = MagicMock()
+        signer.sign_artifact("the-jar.zip", "/path", ".sig")
+        signer.generate_signature_and_verify.assert_called_with("the-jar.zip", "/path", ".sig")
+
+    @patch("sign_workflow.signer.GitRepository")
+    def test_remove_existing_signature_found(self, mock_repo):
+        signer = Signer()
+        os.remove = MagicMock()
+        signer.sign("tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz", ".sig")
+        os.remove.assert_called_with("tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz.sig")
+
+    @patch("sign_workflow.signer.GitRepository")
+    def test_remove_existing_signature_not_found(self, mock_repo):
+        signer = Signer()
+        os.remove = MagicMock()
+        signer.sign("tests/tests_sign_workflow/data/signature/not_found.tar.gz", ".sig")
+        os.remove.assert_not_called()