# Maven Plugin POST but with Gradle

**URL:** <https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879>\
**Category:** Module Development\
**Tags:** ignition81\
**Created:** [July 13, 2022, 11:52pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879 "2022-07-13T23:52:34Z")\
**Posts on this page:** 10\
**Page:** 2

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [July 18, 2022, 4:49pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/21 "2022-07-18T16:49:47Z")

</div>

> [@PerryAJ](#):
>
> (especially if you’re not familiar with the process of creating/getting a cert to sign with)

It’s real hacky, but here’s a power shell script that we use to for self-signing modules with the Gradle plugin. It uses PS to generate a self signed cert, then Java Keytool to create the keystore containing the cert, and then finally creates a gradle.properties file containing all the information needed for the plugin.

This could all be done in a platform independent way in a `selfSignModule` Gradle task, but I’m not sure about the consequences of making it so easy to produce self-signed modules with customizable DNS names.

```auto
$CertStoreLocation = "cert:\CurrentUser\My"
$JavaHome = 'C:\Program Files\Java\jdk-18.0.1\bin'
$FolderName = "signature"

$FolderPath = "$PSScriptRoot\$FolderName"
New-Item $FolderPath -ItemType Directory

$InfoFile = ($FolderPath + "\keystoreinfo.txt")
$GradleProps = ($FolderPath + "\gradle.properties")

$DnsName = Read-Host "Certificate DNS Name"
$YearsBeforeExp = Read-Host "Years before expiration"

Add-Type -AssemblyName System.Web
$CertPassword = [System.Web.Security.Membership]::GeneratePassword(32,4)
$CertPasswordSecure = ConvertTo-SecureString $CertPassword –asplaintext –force 
$KeystorePassword = [System.Web.Security.Membership]::GeneratePassword(32,4)
$KeystoreSecure = ConvertTo-SecureString $CertPassword –asplaintext –force 

$RootFileName = $DnsName.Replace(' ','_')
$RootFilePath = "$FolderPath\$RootFilePath"

$KeystoreFileName = ($RootFileName + "_keystore.jks")
$KeystoreFilePath = "$FolderPath\$KeystoreFileName"

Write-Output "Creating new certificate with DnsName '$DnsName'..."
$Cert = New-SelfSignedCertificate -DnsName $DnsName -Type CodeSigning -CertStoreLocation $CertStoreLocation -NotAfter (Get-Date).AddYears($YearsBeforeExp)

$FileName = "$RootFileName.p7b"
$FilePath = "$FolderPath\$FileName"
Write-Output "Exporting certificate to '$FileName'..."
$Results = Export-Certificate -Cert $Cert -Type P7B -FilePath "$FilePath"

$FileName = "$RootFileName.pfx"
$FilePath = "$FolderPath\$FileName"
Write-Output "Exporting certificate to '$FileName'..."
$Results = Export-PfxCertificate -Cert $Cert -FilePath "$FilePath" -Password $CertPasswordSecure

Write-Output "Removing certificate from personal store..."
$Cert | Remove-Item

$FileName = "$RootFileName.pfx"
Write-Output "Converting '$FileName' to '$KeystoreFileName'..."
$FilePath = "$FolderPath\$FileName"
$Results = Start-Process -FilePath "$JavaHome\keytool.exe" -ArgumentList "-importkeystore -srckeystore .\$FolderName\$FileName -srcstoretype pkcs12 -destkeystore .\$FolderName\$KeystoreFileName -deststoretype JKS -srcstorepass $CertPassword -storepass $KeystorePassword -keypass $CertPassword" -NoNewWindow -PassThru -Wait

Write-Output "Reading key aliases..."
$Results = Start-Process -FilePath "$JavaHome\keytool.exe" -ArgumentList "-list -v -keystore .\$FolderName\$KeystoreFileName -storepass $KeystorePassword" -NoNewWindow -PassThru -RedirectStandardOutput $InfoFile -Wait
$AliasInfo = @(Get-Content -Path $InfoFile | Where-Object { $_.Contains("Alias") })

$AliasName = "ALIAS NOT FOUND"
$line = $AliasInfo[0]
$start = $line.IndexOf(":") + 2
$length = $line.Length - $start
$Alias = $line.Substring($start, $length)
$AliasName = $Alias.Trim()
Write-Output "Alias '$AliasName' found."
#Start-Process -FilePath "$JavaHome\keytool.exe" -ArgumentList "-changealias -alias $Alias -destalias signing_cert -keypass $CertPassword -keystore $RootFileName.jks -storepass $KeystorePassword" -Wait

Write-Output "Generating gradle.properties..."
$content = @"
ignition.signing.certFile= /$FolderName/$RootFileName.p7b
ignition.signing.certPassword= $CertPassword
ignition.signing.certAlias= $AliasName
ignition.signing.keystoreFile= /$FolderName/$KeystoreFileName
ignition.signing.keystorePassword= $KeystorePassword
"@

Add-Content $GradleProps $content

```

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 19, 2022, 4:56pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/22 "2022-07-19T16:56:18Z")

</div>

> [@PerryAJ](#):
>
> We’re going to make that more flexible to ease adoption and make routine development/experimentation a bit simpler for folks.

I think this will be great, that and the minimal perspective example that I know has been talked about on the forums a few times.

> [@PerryAJ](#):
>
> I’d try using fully qualified paths (I personally drop certs in a user home directory). Also think that `ignition.signing.certAlias="My Cert Alias"` probably shouldn’t have quotes.

This solved my problem! I appreciate all of the help!

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 19, 2022, 5:13pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/23 "2022-07-19T17:13:49Z")

</div>

> [@PerryAJ](#):
>
> I figured one would always want a signed module as the end result, but can see how that might be inhibitive for people (especially if you’re not familiar with the process of creating/getting a cert to sign with).

Now, in the vein of not knowing much about module signing, I am running into an issue trying to upload said freshly created/signed module.

Upon uploading I just receive an error that it failed to verify the module, and then the logs show this error:

```auto
com.inductiveautomation.ignition.gateway.modules.ModuleVerificationException: module verification failed
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1605)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.loadModule(ModuleManagerImpl.java:1305)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$2.call(ModuleManagerImpl.java:766)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.executeModuleOperation(ModuleManagerImpl.java:949)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.installModuleInternal(ModuleManagerImpl.java:739)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$InstallCommand.execute(ModuleManagerImpl.java:1905)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$Receiver.receiveCall(ModuleManagerImpl.java:1858)
at com.inductiveautomation.ignition.gateway.redundancy.QueueableMessageReceiver.receiveCall(QueueableMessageReceiver.java:47)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl.dispatchMessage(RedundancyManagerImpl.java:999)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl$ExecuteTask.run(RedundancyManagerImpl.java:1074)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:539)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: signature verification failed
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1600)
... 16 common frames omitted
Caused by: java.security.SignatureException: Signature length not correct: got 256 but was expecting 512
at java.base/sun.security.rsa.RSASignature.engineVerify(Unknown Source)
at java.base/java.security.Signature$Delegate.engineVerify(Unknown Source)
at java.base/java.security.Signature.verify(Unknown Source)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1596)
... 16 common frames omitted

```

I then wanted to try doing it with the unsigned module, so I added the `-Dignition.allowunsignedmodules=true` flag to my conf, and then tried again. However I tried again with the signed module first, and it worked? Any ideas why I was required to add that flag for my signed module to upload?

> [@PerryAJ](#):
>
> After that, seems that running `gradlew deployModl` posts to the developer servlet as intended.

Also, this works great to a gateway on `localhost:8088`, however is it possible to change the url and port with the current version of the plugin? Taking a look at the old plugin, it supports `gatewayUrl` and `gatewayPort` in `ignitionModule`, however I am not seeing anything like that in the current `ModuleSettings.kt`. Not sure if I am missing something, or it just isn't supported yet.

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 19, 2022, 6:39pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/24 "2022-07-19T18:39:33Z")

</div>

> [@kgamble](#):
>
> Also, this works great to a gateway on `localhost:8088`, however is it possible to change the url and port with the current version of the plugin? Taking a look at the old plugin, it supports `gatewayUrl` and `gatewayPort` in `ignitionModule`, however I am not seeing anything like that in the current `ModuleSettings.kt`. Not sure if I am missing something, or it just isn’t supported yet.

To answer my own question, I don't believe it was fully implemented. So I created a PR to do so. I made sure that it works on my side, however here's to hoping that I did it in the best way possible since I just started figured out gradle a couple days ago!

> <https://github.com/inductiveautomation/ignition-module-tools/pull/29>
>
> Currently the \`:deployModl\` task creates a \`hostGateway\` property that is not ac…cessible by the end user. This pull requests adds the setting to the \`ModuleSettings.kt\` file, as well as the \`root.build.gradle\` default file so that the user can change it as well as see how it is used.

---

<div class="post-metadata">

**Author:** ![PerryAJ](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/perryaj/32/3281_2.png) [@PerryAJ](https://forum.inductiveautomation.com/u/PerryAJ)\
**Post date:** [July 20, 2022, 7:01pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/25 "2022-07-20T19:01:01Z")

</div>

> [@kgamble](#):
>
> However I tried again with the signed module first, and it worked? Any ideas why I was required to add that flag for my signed module to upload?

Honestly, not sure. Did you first install the module via the gateway once and accept the certificate? That's the only thing that immediately crosses my mind: the gateway won't load/run a signed module if it doesn't recognize the cert (either due to being one of our whitelisted first-party modules/certs, or because it has yet to be accepted). I _think_ installing it once via the gateway UI and accepting the cert in that process once should satisfy that 'cert was accepted as ok' requirement.

> [@kgamble](#):
>
> Also, this works great to a gateway on `localhost:8088`, however is it possible to change the url and port with the current version of the plugin? Taking a look at the old plugin, it supports `gatewayUrl` and `gatewayPort` in `ignitionModule`, however I am not seeing anything like that in the current `ModuleSettings.kt`. Not sure if I am missing something, or it just isn’t supported yet.

The url and port are configurable as task inputs. If you run `gradlew tasks` you should get some info about the tasks and their flags. As task properties, that means you can override at the commandline:

`gradlew deployModl --gateway https:://some.gateway.net:8099`

If you wanted to use this configuration all the time, you could set the value via the _tasks_ api in the buildscript:

```kotlin
// kotlinscript implementation example
import io.ia.sdk.gradle.modl.task.Deploy;

// down in the buildscript somewhere
tasks {
    withType<Deploy> {
        this.hostGateway.set("https://some.gateway.com:8099")
    }
}

```

---

<div class="post-metadata">

**Author:** ![PerryAJ](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/perryaj/32/3281_2.png) [@PerryAJ](https://forum.inductiveautomation.com/u/PerryAJ)\
**Post date:** [July 20, 2022, 7:03pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/26 "2022-07-20T19:03:51Z")

</div>

> [@kgamble](#):
>
> To answer my own question, I don’t believe it was fully implemented. So I created a PR to do so. I made sure that it works on my side, however here’s to hoping that I did it in the best way possible since I just started figured out gradle a couple days ago!

We'll give this a look. I think @jcoffman has some updates he's going to be working on to ease the 'require signed module to build' aspect. I'll chat with him and we'll see if it makes sense to add the gateway as part of the plugin's configuration extension (aka - the ModuleSettings object).

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 20, 2022, 8:32pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/27 "2022-07-20T20:32:29Z")

</div>

> [@PerryAJ](#):
>
> Did you first install the module via the gateway once and accept the certificate?

This part was actually not talking about using `deployModl` it was talking about manually uploading it directly. So this was while trying to do that

> [@PerryAJ](#):
>
> If you wanted to use this configuration all the time, you could set the value via the _tasks_ api in the buildscript:

Interesting I wasn't aware you could override task properties in this way. If this is the ideal "official" way to do this, it would be good to be in the documentation as well when the plugin is next updated

---

<div class="post-metadata">

**Author:** ![PerryAJ](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/perryaj/32/3281_2.png) [@PerryAJ](https://forum.inductiveautomation.com/u/PerryAJ)\
**Post date:** [July 20, 2022, 9:13pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/28 "2022-07-20T21:13:02Z")

</div>

> [@kgamble](#):
>
> This part was actually not talking about using `deployModl` it was talking about manually uploading it directly. So this was while trying to do that

Hmm, I'll have to look at this, not sure what's going on with that error. Adding the flag will get past it because we simply skip the module signature validation when allowing unsigned modules, but I'm not sure why you're hitting that to begin with. Might be useful to get a copy of the module if you're able to share (can send private message with a link, or email to pjones AT [ia.io](http://ia.io), or whatever mechanism works for you). Module doesn't need to be 'functional', just need to reproduce that error so I can try and figure out an explanation. Alternatively, I can repro how your cert was generated and try to reproduce it that way.

> [@kgamble](#):
>
> Interesting I wasn’t aware you could override task properties in this way. If this is the ideal “official” way to do this, it would be good to be in the documentation as well when the plugin is next updated

Ya, the task-level overrides are increasingly common. I think the shift to kotlin (type-aware) for buildscripts has really helped make that configuration style much easier to use, on account of the autocomplete you get now in supporting IDEs. Trying to configure tasks like that was a bit of a guessing game with the groovy based scripts.

I'll have to look and see if the Gradle team has settled on a 'best practice' for this sort of thing. I increasingly see the task-style configuration used, but not sure if there's a big win in that model vs using the Extension object API. May be that configuration speed is better with the task-level overrides (in particular with build-cache enabled), but would have to investigate.

Either way, I agree we can improve the _README_. Even if we add the property to the ModuleSettings object, the task options/flags/properties will still be configurable and supported in the same way I demo'd, since it's "just how Gradle works".

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [February 2, 2023, 9:43pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/29 "2023-02-02T21:43:40Z")

</div>

> [@PerryAJ](#):
>
> ight be useful to get a copy of the module if you’re able to share (can send private message with a link, or email to pjones AT [ia.io](http://ia.io), or whatever mechanism works for you). Module doesn’t need to be ‘functional’, just need to reproduce that error so I can try and figure out an explanation. Alternatively, I can repro how your cert was generated and try to reproduce it that way.

This is super late, I must have worked around this originally when I first posted this with the unsigned modules flag. However I am now running into it in a production environment with [the following module](https://github.com/keith-gamble/ignition-neo4j).

Would you be able to take a glance at it by chance? A copy of the module is included in the latest release.

I am not sure if its how I am signing it, or my cert specifically.

> **Here is a copy of the stacktrace:**
>
> ```auto
> com.inductiveautomation.ignition.gateway.modules.ModuleVerificationException: module verification failed
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1605)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.loadModule(ModuleManagerImpl.java:1305)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$2.call(ModuleManagerImpl.java:766)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.executeModuleOperation(ModuleManagerImpl.java:949)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.installModuleInternal(ModuleManagerImpl.java:739)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$InstallCommand.execute(ModuleManagerImpl.java:1905)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$Receiver.receiveCall(ModuleManagerImpl.java:1858)
> at com.inductiveautomation.ignition.gateway.redundancy.QueueableMessageReceiver.receiveCall(QueueableMessageReceiver.java:47)
> at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl.dispatchMessage(RedundancyManagerImpl.java:999)
> at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl$ExecuteTask.run(RedundancyManagerImpl.java:1074)
> at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:539)
> at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
> at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
> at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
> at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
> at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
> at java.base/java.lang.Thread.run(Unknown Source)
> Caused by: java.io.IOException: signature verification failed
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1600)
> ... 16 common frames omitted
> Caused by: java.security.SignatureException: Signature length not correct: got 256 but was expecting 512
> at java.base/sun.security.rsa.RSASignature.engineVerify(Unknown Source)
> at java.base/java.security.Signature$Delegate.engineVerify(Unknown Source)
> at java.base/java.security.Signature.verify(Unknown Source)
> at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.verifyModuleSignatures2(ModuleManagerImpl.java:1596)
> 
> ```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [February 2, 2023, 10:17pm UTC](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879/30 "2023-02-02T22:17:59Z")

</div>

> [@kgamble](#):
>
> ```auto
> Caused by: java.security.SignatureException: Signature length not correct: got 256 but was expecting 512
> 
> ```

Your cert public key is 512 bytes, but one or more of the files in your module is signed with a 256 bit/byte key?

[Previous page](https://forum.inductiveautomation.com/t/maven-plugin-post-but-with-gradle/61879.md?page=1)
